JAVA併發編程Fork/Join(分而治之思想)之(Future/Callable)

Java提供Fork/Join框架用於並行執行任務,它的思想就是講一個大任務分割成若干小任務,最終彙總每個小任務的結果從而得到這個大任務的結果。

這裏我們也藉助這種思想來處理一個超大任務的運算,但是不用ForkJoinPool/ForkJoinTask這種方式,而採用ExecutorService/Future/Callable方式。

我們來看一段ExecutorService/Future/Callable方式實現的代碼。

package com.forkjoin;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * JAVA超大數據量計算
 * 求1到100000000的和
 * 解決方案採用多線程拆分任務實現(Future/Callable)
 *
 * @author 小輝GE/小輝哥
 * <p>
 * 2019年8月10日 下午19:30:00
 */
public class ParallelFutureComputing {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 直接執行方式測試
        long start = System.currentTimeMillis();
        getSum(1, 100000000);
        long end = System.currentTimeMillis();
        System.out.println("直接執行耗時時長:" + (end - start));

	// 線程池方式
	ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

        MyThreadTask t1 = new MyThreadTask(1, 25000000);
        MyThreadTask t2 = new MyThreadTask(25000001, 50000000);
        MyThreadTask t3 = new MyThreadTask(50000001, 75000000);
        MyThreadTask t4 = new MyThreadTask(75000001, 100000000);

        // 調用service.submit啓動線程
        Future<Integer> f1 = service.submit(t1);
        Future<Integer> f2 = service.submit(t2);
        Future<Integer> f3 = service.submit(t3);
        Future<Integer> f4 = service.submit(t4);

        start = System.currentTimeMillis();
        // 調用FUTURE.GET的阻塞方法,記錄最終完成的時間
        f1.get();
        f2.get();
        f3.get();
        f4.get();
        end = System.currentTimeMillis();
        System.out.println("Future/Callable執行耗時時長:" + (end - start));
        // 處理完成調用shutdown方法結束線程池
        service.shutdown();
    }

    static class MyThreadTask implements Callable<Integer> {
        Integer begin;
        Integer end;

        MyThreadTask(Integer begin, Integer end) {
            this.begin = begin;
            this.end = end;
        }

        @Override
        public Integer call() throws Exception {
            return getSum(begin, end);
        }
    }

    /**
     * 實現begin到end求和
     *
     * @param begin
     * @param end
     * @return
     */
    static Integer getSum(Integer begin, Integer end) {
        Integer sum = 0;
        for (int i = begin; i <= end; i++) {
            sum = sum + i;
        }
        return sum;
    }
}

測試輸出結果如下:

結果分析:

其實我們很清晰可以看到,單獨執行任務比採用多線程執行任務運行結果所花費的時間多一些。當然,如果任務拆分的合適、運算量足夠大的時候,就更能看出多線程執行和單獨執行的效率差別。

以上代碼僅供參考,如有不當之處,歡迎指出!!!

更多幹貨,歡迎大家關注和聯繫我。期待和大家一起更好的交流、探討技術!!!

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