【JUC并发】fork/join

Fork/Join

原理(需要继承(有返回值)RecursiveTask或者(没返回值)RecursiveAction,重写compute()方法)

将大任务拆分成小任务,先实现compute()方法。首先判断任务是否足够小,如果足够小就直接执行任务。如果不够小,就必须分割成两个子任务,每个子任务调用fork()方法时,又会进入compute()方法,递归下去。

【JUC并发】fork/join_第1张图片

工作窃取算法

【JUC并发】fork/join_第2张图片

异步调用
【JUC并发】fork/join_第3张图片

fork()方法

/**
 *	ForkJoinPool是由ForkJoinTask数组和ForkJoinWorkerThread数组组成。
 *		ForkJoinTask数组负责将存放程序提交给ForkJoinPool的任务
 *		ForkJoinWorkerThread数组负责(异步)执行这些任务
 */
public final ForkJoinTask<V> fork() {
    Thread t;
    if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
        //将当前线程添加到一个工作队列中,然后ForkJoinWorkerThread异步执行这些任务。
        ((ForkJoinWorkerThread)t).workQueue.push(this);
    else
        ForkJoinPool.common.externalPush(this);
    return this;
}
/**
 *	push()方法,将当前任务存放在ForkJoinTask数组队列中。然后再调用ForkJoinPool的signalWork()方法唤醒或创建
 *	一个工作线程来执行任务。
 */
final void push(ForkJoinTask<?> task) {
    ForkJoinTask<?>[] a; ForkJoinPool p;
    int b = base, s = top, n;
    if ((a = array) != null) {    // ignore if queue removed
        int m = a.length - 1;     // fenced write for task visibility
        U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task);
        U.putOrderedInt(this, QTOP, s + 1);
        if ((n = s - b) <= 1) {
            if ((p = pool) != null)
                p.signalWork(p.workQueues, this);
        }
        else if (n >= m)
            growArray();
    }
}

Join()方法

public final V join() {
    int s;
    //调用doJoin()方法得到当前任务的状态。
    //1.已完成(NORMAL)
    //2.被取消(CANCELLED)
    //3.信号(SIGNAL)
    //4.出现异常(EXCEPTIONAL)
    if ((s = doJoin() & DONE_MASK) != NORMAL)
        reportException(s);
    return getRawResult();
}
private void reportException(int s) {
    if (s == CANCELLED)
        throw new CancellationException();
    if (s == EXCEPTIONAL)
        rethrow(getThrowableException());
}
private int doJoin() {
    int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;
   	//通过查看任务状态,看任务是否完成。
    //如果任务已完成,直接返回任务状态
    //如果任务没有完成,则从任务数组中取出任务并执行
    //如果任务顺利执行完成,则设置任务状态为NORMAL
    //如果出现异常,则记录异常,并将任务状态设置为EXCEPTIONAL
    return (s = status) < 0 ? s :
    
    ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
        (w = (wt = (ForkJoinWorkerThread)t).workQueue).
        tryUnpush(this) && (s = doExec()) < 0 ? s :
    wt.pool.awaitJoin(w, this, 0L) :
    externalAwaitDone();
}

使用

public static void test2() throws ExecutionException, InterruptedException {

       long start = System.currentTimeMillis();

       ForkJoinPool forkJoinPool = new ForkJoinPool();
       ForkJoin forkJoin = new ForkJoin(0L, 10_0000_0000L);
       ForkJoinTask<Long> submit = forkJoinPool.submit(forkJoin);
       Long sum = submit.get();
       long end = System.currentTimeMillis();

       System.out.println("时间:"+ (end-start));

   }

class ForkJoin extends RecursiveTask<Long> {

    private Long start;
    private Long end;

    private final Long temp = 10000L;

    public ForkJoin(Long start, Long end){
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {

        Long sum = 0L;
        if((end-start)<temp){
            for (Long i = 0L; i < 10_0000_0000; i++) {
                sum += i;
            }
        }else{
            //ForkJoin
            ForkJoin task1 = new ForkJoin(start, (start + end)/2);
            task1.fork();
            ForkJoin task2 = new ForkJoin((start + end)/2 + 1, end);
            task2.fork();

            sum = task1.join() + task2.join();
        }
        return sum;
    }
}

你可能感兴趣的:(JUC并发,java,并发编程)