Java等待线程完成

我有一个线程下载数据,我想等到下载完成之前我加载数据。 有没有这样做的标准方式?

更多信息:

我有一个下载类,从URL(序列化POJOs)获取数据。 下载是可运行和可观察的。 它跟踪下载的字节和下载大小。 我有一个进度条,向用户显示进度。 GUI观察下载以更新进度条。

当POJO被下载时,我想得到它并转到下一步。 每一步都要等到先前完成。 问题是我不能想办法暂停我的应用程序等待下载线程。 一旦下载完成,我想调用download.getObject(),它将返回数据作为一个对象。 然后,我可以投下它,继续下一个下载。

我有一个帮助类,pipe理下载的URL,并使下载的所有电话。 这个调用将调用getObject并进行转换。 Gui调用helper.getUser()。 助手启动线程运行,我希望它知道什么时候完成,所以它可以返回铸造的对象。

任何build议/例子? 我正处于这个devise的开始阶段,所以我愿意改变它。

非常感谢你。

更新:

我遵循http://download.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html#get并使用模态来阻塞,直到线程完成。 代码非常混乱,我不喜欢这种方法。 我将继续努力寻找一种“干净”的方式来处理下载过程的工作stream程。

Thread有一个方法,为你做。 连接将阻塞,直到线程完成执行。

您可以使用java.util.concurrent包中的CountDownLatch 。 在等待一个或多个线程完成之后,在等待线程中继续执行之前,这是非常有用的。

例如,等待三个任务完成:

 CountDownLatch latch = new CountDownLatch(3); ... latch.await(); // Wait for countdown 

其他线程在完成其任务时调用latch.countDown() 。 一旦倒数完成,在这个例子中三个,执行将继续。

SwingWorker有doInBackground() ,您可以使用它来执行任务。 您可以select执行get()并等待下载完成,也可以覆盖一旦Swingworker完成后将在事件派发线程上执行的done()方法。

Swingworker与您目前的方法相比具有很多优势,因为它具有许多您正在寻找的function,所以不需要重新发明轮子。 您可以使用getProgress()setProgress()方法替代可运行下载进度的观察者。 done()方法如上所述在worker完成执行之后调用,并在EDT上执行,这允许您在下载完成后加载数据。

我想象你在一个后台线程(如SwingWorker提供的)中调用你的下载。 如果是这样,那么只需在同一个SwingWorker的doInBackground方法中依次调用你的下一个代码即可。

通常,当你想等待一个线程完成时,你应该调用join() 。

任何build议/例子? 我跟着SwingWorker …代码非常混乱,我不喜欢这种方法。

而不是等待完成的get() ,使用process()setProgress()来显示中间结果,就像这个简单的例子或这个相关的例子所build议的那样。

join()方法允许一个线程等待另一个线程的完成。然而,和sleep一样,join也依赖于操作系统进行计时,所以你不应该认为连接会按照你指定的那样完全等待。

join()方法的更好的替代方法已经在一段时间内发展了。

ExecutorService.html#invokeAll是一个替代scheme。

执行给定的任务,返回一份持有其状态和结果的期货清单。 Future.isDone()对于返回列表的每个元素都是true。

请注意,完成的任务可能正常结束,或者抛出exception。 如果在进行此操作时修改了给定的集合,则此方法的结果是不确定的。

ForkJoinPool或Executors.html#newWorkStealingPool提供了其他替代方法来实现相同的目的。

示例代码片段:

 import java.util.concurrent.*; import java.util.*; public class InvokeAllDemo{ public InvokeAllDemo(){ System.out.println("creating service"); ExecutorService service = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); List<MyCallable> futureList = new ArrayList<MyCallable>(); for ( int i=0; i<10; i++){ MyCallable myCallable = new MyCallable((long)i); futureList.add(myCallable); } System.out.println("Start"); try{ List<Future<Long>> futures = service.invokeAll(futureList); }catch(Exception err){ err.printStackTrace(); } System.out.println("Completed"); service.shutdown(); } public static void main(String args[]){ InvokeAllDemo demo = new InvokeAllDemo(); } class MyCallable implements Callable<Long>{ Long id = 0L; public MyCallable(Long val){ this.id = val; } public Long call(){ // Add your business logic return id; } } } 

您可以使用join()等待完成所有线程。 在创build线程时,将线程的所有对象保留在全局数组中。 之后保持如下循环:

 for (int i = 0; i < 10; i++) { Thread T1 = new Thread(new ThreadTest(i)); T1.start(); arrThreads.add(T1); } for (int i = 0; i < arrThreads.size(); i++) { arrThreads.get(i).join(); } 

点击这里查看完整的详细信息: http : //www.letmeknows.com/2017/04/24/wait-for-threads-to-finish-java