ForkJoin框架解析

来源:互联网 发布:森女系裙装淘宝店 编辑:程序博客网 时间:2024/06/08 17:50
一、概念
    Fork/Join框架是Java7提供的一个用于并行执行任务的框架,思想是把一个大任务分解成多个小任务,并行执行小任务,最后合并每个小任务的执行结果获得大任务结果。
    work-stealing算法:工作窃取算法,一个线程从其他线程的任务队列中窃取任务来执行,使用双端队列实现。优点:利用多线程进行并行计算;缺点:创建队列增加系统开销。

二、原理
  1.分割任务
    需要一个task类,继承RecursiveTask类,能够递归将任务分割为小任务,直到任务足够小为止。
  2.执行任务、合并结果
    将分割成的子任务分别放入双端队列,启用多个线程分别执行多个任务队列中的任务,任务返回结果后进行合并。
三、基本使用
  1.使用流程
    继承RecursiveTask类,实现compute()方法,创建ForkJoinPool对象,调用pool的invoke(task)/submit(task)方法来执行任务。
    compute()方法中需要定义在任务不满足条件时,继续分割任务,子任务递归调用compute()方法,直到满足足够小的条件再对子任务进行计算并返回结果。
  2.ForkJoinPool构造
    参数有:
    parallelism:可并行级别,决定框架内并行执行的线程数量。
    asyncMode:异步模式,指定任务队列是先进先出模式或后进先出模式。
    通常推荐使用该类的静态方法commonPool()来快速获取ForkJoinPool对象。
  3.核心方法
    fork方法:将子任务放入当前线程的workQueue的双端队列中,框架根据当前正在并发执行ForkJoinTask任务的ForkJoinWorkerThread线程状态,决定让这个任务在队列中等待,或者创建一个新workerThread线程运行它,或者唤醒其他等待任务的workerThread执行它。
    join方法:让当前线程阻塞,直到调用join的子任务执行完并返回结果。如果该子任务在当前线程的任务等待队列workQueue中,则取出该子任务然后递归执行完毕。
四、框架结构
 (一).ForkJoinPool类
    继承AbstractExecutorService类,内部类:WorkQueue、ForkJoinWorkerThreadFactory、EmptyTask。
  1.WorkQueue类
    一个支持工作窃取算法的双端队列,内部由数组实现。包含
    属性:
    taskArray:task数组
    pool:ForkJoinPool,所属的ForkJoinPool对象实例
    owner:ForkJoinWorkerFactory,所属的工作线程;
    方法:
    pushTask(task):在ForkJoinWorkerThread工作的过程中,需要向所属的WorkQueue中添加新的子任务时,会调用pushTask方法。使用Unsafe类的方法将task放入taskArray的top位置,并将top加1;如果当前pool的工作线程较少则调用pool的signalWork(workQueue[],workqueue)方法来创建新的工作线程,如果taskArray空间不足则growArray()。
    pop/poll/peek:获取任务
    runTask(task):执行该task任务,并执行所有该WorkQueue中已经存在的任务。调用task的doexec()方法来调用task的compute()方法,并调用该WorkQueue的execLocalTasks()方法。
    execLocalTasks():如果不是LIFO模式,则遍历获取taskArray数组中的task,调用doExec()方法来调用task的compute()方法来依次执行任务,并将任务依次remove。
    pollAndExecAll():如果是LIFO模式,则调用该方法;
    growArray():增加数组容量。
  2.ForkJoinWorkerThreadFactory接口
    ForkJoinPool的工作线程的工厂接口,pool中提供default实现类。
  3.ForkJoinPool类
    属性:
    common:默认的ForkJoinPool实例;
    workQueues:存放WorkQueue实例的数组
    内部方法:
    externalSubmit(task):初始化pool中workQueue[],数组大小根据并发级别和异步模式有关,且至少是设置的并发级别的2倍。其中奇数位用于存储从外部提交到ForkJoinPool的任务,偶数位用于存储归并计算过程中等待处理的子任务。
    tryAddWorker():尝试添加一个workerThread;
    createWorker():
    signalWork(WorkQueue[],workQueue):将workQueue添加到workQueues中后,调用该方法来根据pool状态来决定唤醒或创建一个工作线程来执行任务。
    scan(WorkQueue,seed):扫描任务队列,获取一个任务。
    实例方法:
    invoke(task):执行并获取返回值;
    execute(task):执行,不返回结果。
    submit(task):执行并返回task自身;
    invokeAll():
 (二).ForkJoinTask类
    内部方法:
    doExec():调用task的compute()方法执行任务
    doJoin():在当前线程中调用join方法来等待子任务执行完毕返回结果
    doInvoke():
    实例方法:
    fork():
    join():
    get():
 (三).ForkJoinWorkerThread类
    ForkJoinPool中的工作线程类,包含
    属性:
    pool:该线程所属的ForkJoinPool实例;
    workQueue:该线程所执行的任务的待执行的子任务的队列,可以被其他工作线程偷取任务。
    方法:
    run():工作线程的主方法,调用pool的runWorker(workQueue)方法,来扫描窃取任务并执行所有该workQueue中的任务。最后调用pool的deregisterWorker()方法来撤销该线程。

五、执行流程
  1.调用pool对象的invoke(task)方法提交任务;
  2.调用pool对象的externalPush(task)方法向pool提交任务;如果pool的workqueues为空,则调用externalSubmit(task)方法;如果pool的workQueues不为空,且当前workerThread未停止&&任务队列不为空&&通过探测数获取的某个workQueue不为空&&成功锁定该workQueue后,则将task放入该workQueue的taskArray中,并将该workQueue的top加1,释放workQueue锁。最后如果该workQueue中的任务数<=1,则调用pool的signalWork(workQueues,workQueue)方法来执行workQueue中的等待任务。
  3.externalSubmit(task)方法:如果workQueues为空,则根据pool的参数并发级别和异步模式来初始化一个长度合适的数组;通过探测数获取一个workQueue,如果不为null则将task放入该workQueue的taskArray中,成功后调用signalWork;如果获取的workQueue为null,则创建一个shared workQueue,继续尝试将task放入workQueue中。
  4.signalWork()方法:当成功添加一个任务后调用,目的是可能需要增加一个workerThread来工作。如果活动线程数满则break;如果没有处于等待状态的workerThread且现场数未满则tryAddWorker()并开始工作,break;尝试唤醒一个等待的workerThread来工作,成功则break,失败则根据workQueue中任务数判断是否重来。
  5.workerThread的run()方法:工作线程的工作方式。调用pool的runWorker(workQueue)方法来执行workQueue中的任务。执行完毕则撤销当前workerThread。
  6.runWorker()方法:调用workQueue的growArray()方法来扩充数组,调用pool的scan(workQueue,r)方法来扫描该任务队列获取一个任务,并执行该任务,如果该任务为空则阻塞当前线程并返回;
  7.scan(workQueue,r)方法:扫描workQueues,获取一个workQueue,如果该workQueue不为空,则从其taskArray中获取一个task,调用signalWork()来执行该workQueue并返回该task,即窃取一个任务;
  8.runTask(task):执行任务;设置workQueue的窃取任务为该task,调用该task的deExec()方法,将workQueue的窃取任务置为null;然后调用workQueue的execLocalTasks()方法;