本文属原创,转载请注明出处:http://www.cnblogs.com/robinjava77/p/5455207.html (Robin)
业务场景是这样的:
1.定义了一个抽象类:抽象类有有两个方法main()和business();
2.main()是具体方法,规范了业务流程;business()是抽象方法,由各个子类实现具体的业务逻辑;
3.main()里面有一不调用business(),由于business()比较费时,而且main需要多次调用business,所以main要能异步调用business()
4.main异步调用business()后,继续其他工作,完成其他工作后,等待所有business完成各自的流程,返回结果给main,然后main再统一继续剩余流程
具体办法,还在思考...
2016.05.03
---------------------------------------------------
新解决方案
1.使用java.util.concurrent.CompletionService 来对异步执行的任务进行添加和获取反馈结果;
1 import java.util.concurrent.*; 2 3 /** 4 * Created by robin on 2016/5/4. 5 * 6 * @author robin 7 */ 8 public class MyFutureTaskTest { 9 10 public static void main(String[] args) throws Exception { 11 int n = 4; 12 ExecutorService threadPool = Executors.newCachedThreadPool(); 13 CompletionService<Integer> cs = new ExecutorCompletionService<Integer>(threadPool); 14 for(int i=0;i<n;i++){ 15 final int temp = i; 16 cs.submit(new Callable<Integer>() { 17 public Integer call() throws Exception { 18 int i = business(temp); 19 return i; 20 } 21 }); 22 System.out.println("main在继续进行流程规范,循环次数:" + (i+1)); 23 } 24 System.out.println("循环已结束,main在执行其他流程规范。"); 25 System.out.println("main执行完其他流程规范,现在开始等待异步调用的business()群执行完毕,才能继续"); 26 int result = 0; 27 for(int i=0;i<n;i++){ 28 result += cs.take().get();//自动获取当前池中最先完成的任务反馈结果,若此时没有,则阻塞 29 } 30 System.out.print("business已异步跑完,计算结果:"+result); 31 } 32 33 public static Integer business(int i) throws InterruptedException { 34 System.out.println("开始执行business方法,标志号:" + i); 35 Thread.sleep(5000);// 36 System.out.println("business执行完毕,标志号:"+i); 37 return i; 38 } 39 }
执行结果
main在继续进行流程规范,循环次数:1 main在继续进行流程规范,循环次数:2 main在继续进行流程规范,循环次数:3 main在继续进行流程规范,循环次数:4 循环已结束,main在执行其他流程规范。 main执行完其他流程规范,现在开始等待异步调用的business()群执行完毕,才能继续 开始执行business方法,标志号:0 开始执行business方法,标志号:1 开始执行business方法,标志号:3 开始执行business方法,标志号:2 business执行完毕,标志号:0 business执行完毕,标志号:1 business执行完毕,标志号:3 business执行完毕,标志号:2 business已异步跑完,计算结果:6 Process finished with exit code 0
2016.05.04
---------------------------------------------------
旧解决方案(已使用新解决方案):
1.使用java.util.concurrent.Future类,来异步执行business(),并且返回执行后的结果;
2.使用java.util.concurrent.CountDownLatch类,来对异步执行的Future群,进行同步管理;
具体代码:
1 package concurrentTest; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 import java.util.concurrent.*; 6 7 /** 8 * Created by robin on 2016/5/3. 9 * 10 * @author robin 11 */ 12 public class MyFutureTaskTest { 13 14 public static void main(String[] args) throws Exception { 15 int n = 4; 16 final CountDownLatch doneFlag = new CountDownLatch(n);//结束倒数锁 17 Map<String,Future<Integer>> threadMap = new HashMap<String,Future<Integer>>();//异步线程执行返回结果容器 18 Future<Integer> future = null; 19 for(int i=0;i<n;i++){ 20 final int temp = i; 21 ExecutorService threadPool = Executors.newCachedThreadPool(); 22 future = threadPool.submit(new Callable<Integer>() { 23 public Integer call() throws Exception { 24 int i = business(temp); 25 doneFlag.countDown();//通知结束倒数锁本线程完成计算 26 return i; 27 } 28 }); 29 threadMap.put("" + i, future); 30 System.out.println("main在继续进行流程规范,循环次数:" + (i+1)); 31 } 32 System.out.println("循环已结束,main在执行其他流程规范。"); 33 System.out.println("main执行完其他流程规范,现在开始等待异步调用的business()群执行完毕,才能继续"); 34 doneFlag.await();//父线程等待所有子线程完成计算 35 int result = 0; 36 for (Map.Entry<String,Future<Integer>> entry:threadMap.entrySet()){ 37 result += entry.getValue().get();//获取每个business执行后的结果 38 } 39 System.out.print("business已异步跑完,计算结果:"+result); 40 41 } 42 43 public static Integer business(int i) throws InterruptedException { 44 System.out.println("开始执行business方法,标志号:" + i); 45 Thread.sleep(5000);// 46 System.out.println("business执行完毕,标志号:"+i); 47 return i; 48 } 49 50 }
执行结果
main在继续进行流程规范,循环次数:1 main在继续进行流程规范,循环次数:2 main在继续进行流程规范,循环次数:3 main在继续进行流程规范,循环次数:4 循环已结束,main在执行其他流程规范。 main执行完其他流程规范,现在开始等待异步调用的business()群执行完毕,才能继续 开始执行business方法,标志号:1 开始执行business方法,标志号:3 开始执行business方法,标志号:2 开始执行business方法,标志号:0 business执行完毕,标志号:1 business执行完毕,标志号:2 business执行完毕,标志号:3 business执行完毕,标志号:0 business已异步跑完,计算结果:6 Process finished with exit code 0
2016.05.03