• 同级方法异步调用(2016.05.04更新)


    本文属原创,转载请注明出处: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

  • 相关阅读:
    一个ball例程带你进入 Halcon 世界
    新公民读本
    open_window()到底做了什么?
    duilib学习领悟(4)
    duilib学习领悟(3)
    duilib学习领悟(2)
    通过Vue路由传参的两种方式及Vue组件中接收参数的方式
    彻底研透javascript中的对象及面向对象编程
    thinkphp5中使用phpmailer实现发送邮件功能
    小程序和ThinkPHP5结合实现登录状态(含代码)
  • 原文地址:https://www.cnblogs.com/robinjava77/p/5455207.html
Copyright © 2020-2023  润新知