Javaタスクの分割

13363 ワード

Javaバックエンドの開発過程では、大きなタスク量の計算やタスクの実行に遭遇することがよくあります.この場合、java jdkに付属する分割思想と方法を使用することができます.分割タスクは主に2つの抽象クラスに依存しています.1つはRecursiveActionで、戻り値を必要としないタスクを実行する場合、このクラスを継承することができます.一つはRecursiveTaskで、これはRecursiveActionの親です.彼は戻り待ち値を塞いで、相応の計算結果を得ることができます.ここでは戻り値のある例を挙げて、1から100を計算して、3つの数ごとに1つの計算に分けて、バッチ計算の統合を完成します.
public class ComplexCaculateTask extends RecursiveTask<Integer> {
    private static final long serialVersionUID = -4068008344384908582L;
    private Integer max_limit = 3;
    private Integer start;
    private Integer end;
 
    public ComplexCaculateTask(Integer start, Integer end) {
        this.start = start;
        this.end = end;
    }
 
    @Override
    protected Integer compute() {
        Integer sum = 0;
        if (start - end <= max_limit) {
            for (int i = start; i <= end; i++) {
                sum += i;
            }
        } else {
            //    2 
            int middle = (end + start) / 2;
            ComplexCaculateTask leftTask = new ComplexCaculateTask(start, middle);
            ComplexCaculateTask rightTask = new ComplexCaculateTask(middle, end);
            //    
            leftTask.fork();
            rightTask.fork();
            //     
            Integer leftResult = leftTask.join();
            Integer rightResult = rightTask.join();
            sum = leftResult + rightResult;
        }
        return sum;
    }
 
    public Integer computeSum() {
        Integer sum = 0;
        for (int i = start; i <= end; i++) {
            sum += i;
        }
        return sum;
    }
 
    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ComplexCaculateTask task = new ComplexCaculateTask(1, (Integer) Integer.MAX_VALUE / 10);
        Future<Integer> result = forkJoinPool.submit(task);
        try {
            System.out.println("    : " + result.get());
            System.out.println("    : " + (System.currentTimeMillis() - start) + " ms.");
            System.out.println("    : " + task.computeSum());
            System.out.println("    : " + (System.currentTimeMillis() - start) + " ms.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        forkJoinPool.shutdown();
    }
}

ForkJoinPoolというクラスはExecutorServiceインタフェースを実現し,futureで計算結果の戻りを待ち,スレッドプールを閉じる.計算プロセス全体はタスクの組合せ結果を分割する考え方であり,大きなタスクの下のシーンでは計算や実行効率を向上させ,cpuなどを有効に利用することができる.ForkJoinPool poll=new ForkJoinPool()のデフォルトでは、既存の処理個数と同じスレッド数を作成してタスクを実行し、リソースを合理的に活用します.