2012-03-20 100 views
6

我有一个多线程的实现,我创建一个ExecutorService并提交要执行的任务,我想知道什么时候所有线程都已完成而没有阻塞主线程和UI。我试过ExecutorService.awaitTermination(),但它阻止了主线程和用户界面。我搜索了很多,但我似乎无法找到一个这样做的优雅方式。我目前正在考虑创建另一个线程来计算完成的线程数量,并在完成时启动一个事件,但这不是一个好方法,而且我想要一个更好的解决方案!ExecutorService,如何知道所有线程何时完成而不阻塞主线程?

+0

你的主线程做的,它不能被阻止什么? – EJP 2012-03-20 00:42:58

+0

你使用什么UI工具包? – Dev 2012-03-20 00:44:12

回答

2

isTerminated()会做

不过请注意,这两个awaitTerminationisTerminated只会给你一个有意义的结果,你都呼吁shutdown

+0

我发现了一些关于isTerminated()的内容,但仍然认为我需要在“side thread”上运行它来经常检查它是否返回true,从而将我带入我的初始解决方案! – Trota 2012-03-20 00:15:11

7

使用SwingWorker来关闭线程池,并调用awaitTermination()后。这将防止UI阻塞,并从SwingWorker实现上的Event Dispatch Thread中调用done(),您可以使用它来触发您所需的任何UI更改。

如果您希望跟踪通过UI更新运行的线程,则可以使用工作线程在一个循环中监控此线程,并调用publish(),然后将参数传递给EDT上的process()实现。

+1

他从来没有提到这是一个Swing应用程序,如果没有,那么SwingWorker将不合适。 – 2012-03-20 00:37:12

+1

我忘了提及它是一个Swing应用程序! – Trota 2012-03-20 00:44:42

+0

阅读了更多关于SwingWorker后,我意识到这是一个相当简单的解决方案,我的问题!谢谢Dev! – Trota 2012-03-20 00:50:55

4

为什么不使用CountDownLatch,然后在闩锁完成时通知主线程。

+1

好主意;有一个很好的例子[这里](http://stackoverflow.com/a/3588523/230513)。 – trashgod 2012-03-20 05:09:53

+1

@trashgod刚刚在你的文章中留言:这个例子在访问文本组件的EDT时出现了一个小故障 – kleopatra 2012-03-20 11:20:52

2

您可以维护一个单独的线程在执行服务实例关闭追踪:

final ExecutorService execSvc = ...; 
    execSvc.submit(task1); 
    ... 
    execSvc.submit(taskN); 
    // important to request the exec service to shut down :) 
    execSvc.shutdown(); 

    new Thread(new Runnable() { 

     public void run() { 
      while (!execSvc.isTerminated()) { 
       try { 
        execSvc.awaitTermination(60, TimeUnit.SECONDS); 
       } catch (InterruptedException e) { 
        // ignore exception 
       } 
      } 
      System.out.println("ExecSvc.run: exec service has terminated!"); 
      // possibly submit a task using SwingUtilities.invokeLater() to update the UI 
     } 

    }).start(); 
2

使用CountDownLatch

 

CountDownLatch latch = new CountDownLatch(totalNumberOfTasks); 
ExecutorService taskExecutor = Executors.newFixedThreadPool(4); 
while(...) { 
    taskExecutor.execute(new MyTask()); 
} 

try { 
    latch.await(); 
} catch (InterruptedException E) { 
    // handle 
} 

,你的任务中

(在尝试/最后附上)
 latch.countDown(); 

或者在您调用shutdown()的ExecutorService上,然后在awa itTermination()

 
ExecutorService taskExecutor = Executors.newFixedThreadPool(4); 
while(...) { 
    taskExecutor.execute(new MyTask()); 
} 
taskExecutor.shutdown(); 
try { 
    taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); 
} catch (InterruptedException e) { 
    ... 
} 

也看看THIS答案

+0

除非我误解了我的理解,否则这两种解决方案都不能解决OP的基本问题,即避免主要阻塞线。 – Trevor 2014-06-22 12:41:14

相关问题