Java併發基礎(九)-Fork/Join框架

1. 什麼是Fork/Join框架

Java 1.7 中提供了Fork/Join框架,實現了work-stealing算法(工作竊取算法),什麼意思呢?就是說,我可以把當前任務分割成多個小任務,讓空閒的線程也進行工作,是不是很贊,這樣,就能最大限度的利用資源,從而提升效率。

哈,這裏就補全線程池基礎那篇文章了,java 1.8 提供的newWorkStealingPool,就是用這個實現的。

2. 包括哪些內容呢

包括一下內容:

  • ForkJoinPool 實現工作竊取算法的線程池
  • ForkJoinTask ForkJoinPool中執行的任務的基類,這個類中有幾個比較重要的方法,根據不同的需求去實現他的兩個子類
    • fork 執行任務
    • join 返回結果
  • RecursiveAction ForkJoinTask的一個子類,含任務執行結果
  • RecursiveTask ForkJoinTask的另一個子類,不含任務執行結果
    • 我們都需要實現這兩個子類的 compute方法,更具需求切分任務

我這裏就不在介紹api了,有興趣的同學自行fuck 文檔或者源碼中的註釋。

3.舉個例子?

舉個例子來說明效率的提升。舉個什麼樣的例子呢?遍歷文件,這個好。看下普通用法和輸出結果(一會對比輸出結果)。

    private static void noForkJoin(){
        File file = new File("/home/guolei/geek");
        long start = System.currentTimeMillis();
        long length = getFileCount(file);
        System.err.println("noForkJoin ----> 文件數目"+length);
        System.err.println( "noForkJoin ----> 耗時" + (System.currentTimeMillis() - start) + "ms");
    }

    private static long getFileCount(File file){
        long count = 0;
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()){
               count += getFileCount(files[i]);
            }else {
                count ++;
            }
        }
        return count;
    }

裝b程序員寫法:

1 首先,我們得實現RecursiveTask,因爲我們需要結果。

    private static class CustomTask extends RecursiveTask<Long>{

        private File file;
        public CustomTask(File file){
            this.file = file;
        }
        @Override
        protected Long compute() {
            long count = 0L;
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                if (files[i].isDirectory()){

                        CustomTask customTask = new CustomTask(files[i]);
                        customTask.fork();
                        count += customTask.join();

                }else {
                    count ++;
                }
            }
            return count;

2 其次,我們創建ForkJoinPool和Task並執行,

        File file = new File("/home/guolei/geek");
        long start = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        CustomTask customTask = new CustomTask(file);
        Future<Long> future = forkJoinPool.submit(customTask);
        try {
            System.err.println("forkJoin -----> 文件數目" + future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.err.println( "forkJoin -----> 耗時" + (System.currentTimeMillis() - start) + "ms");

代碼就這麼一點,那麼我們來對比下耗時。截圖如下:

這裏寫圖片描述

我這裏文件還不是很多,但是提升已經很明顯了。。。

有沒有get到這個技能呢?拿去!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章