java并发Fork/join框架-java并发编程的艺术

来源:互联网 发布:用户注册cms 编辑:程序博客网 时间:2024/04/28 20:29
package testforkandjoin;import java.util.concurrent.ForkJoinPool;import java.util.concurrent.ForkJoinWorkerThread;import java.util.concurrent.Future;import java.util.concurrent.RecursiveTask;//RecursiveTask extends ForkJoinTask 用于有返回结果的任务//RecursiveAction extends ForkJoinTask 用于没有返回结果的任务//ForkJoinTask需要通过ForkJoinPool来执行/** *  * 工作窃取算法 * 干完活的线程,帮助其他线程干活,造成竞争,所以使用双端队列,被窃取任务线程从双端队列的头部拿任务执行,而窃取任务的线程从双端队列的尾部拿任务执行 * 优点:充分利用线程进行并行计算,减少了线程间的竞争 * 缺点:当双端队列里只有一个任务时,存在竞争。该算法会消耗过多的系统资源,创建了多个线程和双端队列 * @ClassName: CountTask  * @Description: TODO(当一个工作线程的队列中暂时没有任务时,它会随即从其他线程的队列尾部获取一个任务)  * @author 梦境迷离   * @date 2017-8-7 下午5:00:38  * */public class CountTask extends RecursiveTask<Integer> {/**  * @Fields serialVersionUID : TODO(用一句话描述这个变量表示什么)  */ private static final long serialVersionUID = 1L;/**  * @Title: main  * @Description: TODO(这里用一句话描述这个方法的作用)  * @param @param args    设定文件  * @return void    返回类型  * @throws  */private static final int THRESGOLD = 2;//阈值private int start;private int end;public CountTask(int start, int end){this.start = start;this.end = end;}public static void main(String[] args) {ForkJoinPool forkJoinPool = new ForkJoinPool();//生成计算任务,负责计算1+2+3+4CountTask task = new CountTask(1, 4);//执行一个任务Future<Integer> result  =  forkJoinPool.submit(task);if(task.isCompletedAbnormally()){System.out.println(task.getException());//检查是否跑出异常,或已经取消任务,取消:CancellationException,未完成/没有异常:null}try {System.out.println(result.get());} catch (Exception e) {// TODO: handle exception}}@Overrideprotected Integer compute() {int sum = 0;//如果任务足够小就计算任务boolean canCompute = (end-start)<=THRESGOLD;if(canCompute){for(int i=start; i<=end; i++){sum+=i;}}else {//如果任务大于阈值,就分裂成两个小任务计算int middle = (start+end)/2;CountTask lefTask = new CountTask(start, middle);CountTask rightTask = new CountTask(middle+1, end);//执行子任务//子任务1负责执行1+2,子任务2负责执行3+4lefTask.fork();rightTask.fork();//等待子任务执行完,并得到结果int leftResult = lefTask.join();int rightResult = rightTask.join();//合并任务sum = leftResult+rightResult;}return sum;}}/** * ForkJoinPool由ForkJoinTask数组和ForkJoinWorkerThread数组组成 * ForkJoinTask数组负责将存放程序交给ForkJoinPool的任务,而ForkJoinWorkerThread数组负责执行这些任务 *  * ForkJoinTask的fork方法内部调用了ForkJoinWorkerThread的pushTask方法,pushTaks方法把当前任务存放在ForkJoinTask数组队列中, * 然后调用ForkJoinPool的signalWork()方法唤醒或创建一个工作线程来执行任务 *  * ForkJoinTaskd join方法内部调用了doJoin方法,通过该方法得到任务的状态, * 1、已完成--返回结果 * 2、被取消--跑出Cancellation异常 * 3、信号-- * 4、异常--直接抛出对应的异常 * doJoin方法中, * 1、查看任务状态 * -是否执行完成 * 是-返回任务状态 * 否-从任务数组中取出任务并执行 * -顺利完成--状态设置为normal * -出现异常--记录异常,状态设置为exceptional *  *  */


原创粉丝点击