Fork/Join

7.1 Future任务机制与FutureTask

future提供: ① 判断任务是否完成;② 能够中断任务; ③ 能够获取任务执行结果;

futureTask:  构造

        ① public FutureTask(Callable callable);创建一个任务,一旦运行就执行给定的Callable;

    ② public FutureTask(Runnable runnable, V result);创建一个任务,一旦运行就执行给定的Runnable,成功完成时返回给定结果;

 

7.2 Fork/Join框架

JDK7提供的用于并行执行任务的框架,把大任务分割成若干小任务,最终汇总每个小任务结果后得到大任务结果的框架;

Fork/Join_第1张图片

 

ForkJoinTask与一般任务的主要区别在于它需要实现compute方法,这个方法中,首先需要判断任务是否够小,如果足够小就直接执行任务。如果不够小,就切分任务,每个子任务调用fork()时,再次进入compute(),再次判断是否需要进一步切分,如果不需要分割,则执行当前子任务并返回结果。使用join()会等待子任务执行完成并得到其结果。

 

Fork/Join_第2张图片

 

Fork/Join_第3张图片

 

ForkJoinTask 是实现Future的另一种有返回结果的实现,比Future多两个方法

    fork() : 决定了ForkJoinTask 的异步执行,凭借这个方法可以创建新的任务。

    Join() : 负责计算完成后返回结果,因此允许一个任务等待另一个任务执行完成。

    ForkJoinTask需要通过ForkPool来执行,任务分割出的子任务会添加到当前工作线程锁维护的双端队列中,进入队列头部。

    当一个工作线程的队列里暂时没有任务时,它会随机从其他工作线程的队列尾部获取一个任务。

 

 

RecursiveAction: 继承ForkJoinTask,用于没有返回结果的任务。

RecursiveTask: 继承ForkJoinTask,用于有返回结果的任务。

ForkJoinPool: 和线程池ThreadPoolExecutor一样都是实现Executor接口。

 

ForkJoinPool 提供三个方法调度子任务:

    Execute( ); 异步执行指定的任务;

    Invoke( ); invokeAll( ); 执行指定的任务,等待完成,返回结果;

    Submit( ); 异步执行指定的任务,并立即返回一个Future对象。

    

 

7.3 Fork/Join框架的实现原理

是一个特殊的线程池框架,专用于需要将一个任务不断分解,再不断汇总得到结果的计算过程。

实现了工作窃取算法:当一个线程空闲的时候,可以从其他线程的队列窃取任务来执行【每个线程应该从队列头部得到任务,而窃取线程将从其他线程的队列尾部得到任务】。

        优点:充分利用线程进行并行运算,减少了线程之间的竞争

        缺点:某些情况下还是存在竞争【比如双端队列只有一个任务时】;并且消耗了更多的系统资源【创建多个线程和多个双端队列】

 

ForkJoinPool由ForkJoinTask数组和ForkJoinWorkThread数组组成,

        ForkJoinTask数组:负责存放程序提交给ForkPool的任务;

                ForkJoinTask.fork( ); //调用该方法时,程序会调用push( ) 【把当前任务放在ForkJoinPool.WorkQueue[ ] 中】异步执行这个任务,然后立即返回结果。

                ForkJoinTask.join( ); //主要作用:阻塞当前线程并等待获取结果。

                        ① 调用doJoin( ) ,首先查看任务状态,是否已经执行完成,完成则直接返回任务状态;未完成则从任务数组中取出任务并执行;

                                如果任务顺利执行完成,设置为NORMAL;出现异常,设置为EXCEPTIONAL;

                        ②  externalAwaitDone( ) 方法中使用了同步代码块锁机制和interrupt阻塞机制;

                        ③ 得到当前任务的状态来判断返回结果【NORMAL: 已完成; CANCELLED: 被取消; SIGNAL: 信号; EXCEPTIONAL: 异常;】

                                NORMAL: 直接返回结果;

                                CANCELLED: 直接抛出CancellationException;

                                EXCEPTIONAL: 直接抛出对应的异常;

        ForkJoinWorkThread数组:负责执行任务;

 

7.4 异常处理

ForkJoinTask在执行的时候可能会抛出异常,但无法在主线程中直接捕获;

ForkJoinTask提供了 isCompletedAbnormally( ); 方法检查任务是否已经抛出异常或被取消,并且可以通过ForkJoinTask.getException( ); 获取异常;

        ForkJoinTask.getException( ); 返回Throwable对象,如果任务被取消了,则返回CancellationException; 如果任务没有完成或者没有抛出异常,返回null;

 

 

7.5 优缺点

优点:

        方便的利用多核平台的计算能力实现并发任务的拆分,极大的简化了编写并发程序的琐碎工作。

        对于该模式下的应用,不再需要处理并行事务【同步、同信、死锁、data race…】。

缺点:

        需要注意,如果拆分对象过多,短时间内将内存撑满。等待线程的CPU资源释放了,但线程对象等待时不会被垃圾回收机制回收;

 

        

 

 

 

 

 

你可能感兴趣的:(Fork/Join)