多任务异步执行 全部执行完执行回调问题

改改心情
  • 399
var total = 7
var complete_total = 0
fun start(){
   complete_total = 0
   for(i in 0-7){ 
      // 异步任务
      task.run(object:Callback(){
         ...
         final(){ 
           complete_total++ 
           if(complete_total == total){ 
             completeAll()
           }
         }
      }) 
   }
}
fun completeAll(){
   // 全部执行完毕
}

大概就会上面的代码
但是打印complete_total,打印了7次

1==7
2==7
3==7
4==7
4==7
5==7
6==7

请问下这是什么原因吗?
有什么办法保证全部任务执行完毕后再回调吗?

回复
阅读 1.5k
4 个回答
𝒁𝒉𝒋𝒍37
  • 2k
✓ 已被采纳
推荐使用ReactiveX吧,Rx 特别擅长处理这类异步任务

题主问题可以使用 Zip操作符 来解决,而且能规避题主自己回答中缺少异常处理的问题。
http://reactivex.io/documenta...

青灯客
  • 24

我的方案使用原子int变量,每个线程执行完后调用一个检测方法,这种在最后一个线程执行完后会被触发,不会阻塞当前线程运行,CountDownLatch形式会造成其所在线程阻塞,譬如在线程A开启
8个线程,目的想等8个线程执行完后执行一段代码,使用我的方式,则A线程不会阻塞,8个线程顺利执行完后会执行你想要执行的代码,CountDownLatch会阻塞线程A,令其无法继续执行,wait()方法有无参跟有参两种意味着是A线程等待无限期或有限时间,意味着有两种风险,无参wait()-》一旦某一个线程出错未成功执行,则A线程永远阻塞,有参wait(【时间】)-》8个线程可能未完全执行完,导致原本需要完整运行完8个线程后执行的代码逻辑发生错误。

伪代码:

private AtomicInteger count;
new Thread(new Runnable{
@Override
void run(){
  checkComplete();
 }
}).start();

boolean checkComplete(){
 int andGet = count.addAndGet(1);
 if(andGet==线程数){
   //todo 所有线程完成
 }
}

方法有很多 CountDownLatchCyclicBarrier 都能做,方式都差不多,使用线程池也行。


        Callable<Void> callable = () -> {
            System.out.println("one");
            return null;
        };

        List<Callable<Void>> list = Lists.newArrayList();
        for(int i = 0;i < 7;i++){
            list.add(callable);
        }
        ExecutorService service = Executors.newFixedThreadPool(7);

        service.invokeAll(list);
        service.shutdown();

        System.out.println("end");

定义一个CountDownLatch
private var tasks = CountDownLatch(2)

新起一个线程等待任务完成

Thread{
    tasks.await()
    // 任务完成后需要执行的代码放这里
}.start()

异步任务内执行完毕后调用
tasks.countDown()

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏