等待所有线程在java中完成其工作
我正在编写一个应用程序,它有5个线程,可以同时从web获取一些信息,并在缓冲区类中填充5个不同的字段。等待所有线程在java中完成其工作,java,multithreading,wait,Java,Multithreading,Wait,我正在编写一个应用程序,它有5个线程,可以同时从web获取一些信息,并在缓冲区类中填充5个不同的字段。 我需要验证缓冲区数据,并在所有线程完成其工作后将其存储在数据库中。 我如何才能做到这一点(当所有线程完成其工作时得到警报) 您可以添加到线程。连接将阻塞,直到线程完成 for (Thread thread : threads) { thread.join(); } 请注意,join抛出一个InterruptedException。如果发生这种情况,您必须决定要做什么(例如,尝试取消其
我需要验证缓冲区数据,并在所有线程完成其工作后将其存储在数据库中。
我如何才能做到这一点(当所有线程完成其工作时得到警报) 您可以添加到线程。连接将阻塞,直到线程完成
for (Thread thread : threads) {
thread.join();
}
请注意,join
抛出一个InterruptedException
。如果发生这种情况,您必须决定要做什么(例如,尝试取消其他线程以防止不必要的工作被完成)。您可以这样做
for (Thread t : new Thread[] { th1, th2, th3, th4, th5 })
t.join()
在此for循环之后,您可以确保所有线程都已完成其作业。您可以使用此方法。将线程对象存储到某个集合中(如列表或集合),然后在线程启动后循环收集并调用线程。可以使用executor服务管理多个线程,包括状态和完成。参见除了别人建议的
Thread.join()
之外,Java5还引入了executor框架。在这里,您不能使用线程
对象。相反,您将Callable
或Runnable
对象提交给执行者。有一个特殊的执行器,用于执行多个任务并按顺序返回结果。这就是:
然后可以重复调用take()
,直到不再有Future
对象返回,这意味着所有对象都已完成
根据您的场景,另一件可能相关的事情是 一种同步辅助工具,允许一组线程都等待对方到达一个共同的障碍点。CyclicBarrier在涉及固定大小的线程组的程序中很有用,这些线程有时必须互相等待。该屏障被称为循环屏障,因为它可以在释放等待的线程后重新使用
我所采用的方法是使用一个线程池来管理线程池
ExecutorService es = Executors.newCachedThreadPool();
for(int i=0;i<5;i++)
es.execute(new Runnable() { /* your task */ });
es.shutdown();
boolean finished = es.awaitTermination(1, TimeUnit.MINUTES);
// all tasks have finished or the time has been reached.
Executors服务=Executors.newCachedThreadPool();
对于(int i=0;i另一种可能性是对象,这对于简单的情况很有用:因为您预先知道线程的数量,所以可以使用相关计数初始化它,并将对象的引用传递给每个线程。
在完成其任务后,每个线程调用CountDownLatch.countDown()
,这将递减内部计数器。主线程在启动所有其他线程后,应执行CountDownLatch.await()
阻塞调用。一旦内部计数器达到0,它将被释放
请注意,对于此对象,也可以抛出一个中断异常。虽然与OP的问题无关,但如果您对仅一个线程的同步(更准确地说,rendez-vous)感兴趣,可以使用
在我的例子中,我需要暂停父线程,直到子线程执行某些操作,例如完成其初始化。A也可以正常工作。试试这个,它会正常工作
Thread[] threads = new Thread[10];
List<Thread> allThreads = new ArrayList<Thread>();
for(Thread thread : threads){
if(null != thread){
if(thread.isAlive()){
allThreads.add(thread);
}
}
}
while(!allThreads.isEmpty()){
Iterator<Thread> ite = allThreads.iterator();
while(ite.hasNext()){
Thread thread = ite.next();
if(!thread.isAlive()){
ite.remove();
}
}
}
Thread[]threads=新线程[10];
List allThreads=new ArrayList();
用于(线程:线程){
if(null!=线程){
if(thread.isAlive()){
添加(线程);
}
}
}
而(!allThreads.isEmpty()){
迭代器ite=allThreads.Iterator();
while(ite.hasNext()){
Thread Thread=ite.next();
如果(!thread.isAlive()){
删除();
}
}
}
在主线程中使用它:while(!executor.isTerminated());
在从executor服务启动所有线程后放入这行代码。这将仅在executor启动的所有线程完成后启动主线程。请确保在上述循环之前调用executor.shutdown()。查看各种解决方案
join()
执行给定的任务,当所有任务都完成时,返回保存其状态和结果的未来列表
有关代码示例,请参阅此相关SE问题:
一种同步辅助工具,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成
for (Thread thread : threads) {
thread.join();
}
使用给定的计数初始化CountDownLatch。由于调用countDown()函数,等待方法会一直阻塞,直到当前计数达到零为止< /代码>方法,在此之后,所有等待线程被释放,随后的任何调用等待立即返回。这是一次性的现象——计数不能重置。如果需要重置计数的版本,请考虑使用<强> CyclicBarrier < /强> 。
有关countdownlock
或者
迭代提交到ExecutorService
我也遇到了类似的问题,最终使用了Java8ParallelStream
requestList.parallelStream().forEach(req -> makeRequest(req));
它超级简单易读。
在幕后,它使用默认JVM的fork-join池,这意味着它将等待所有线程完成后再继续。对于我来说,这是一个不错的解决方案,因为它是我的应用程序中唯一的并行流。如果同时运行多个并行流,请阅读下面的链接
关于并行流的更多信息。现有答案说可以join()
每个线程
但是有几种方法可以获取线程数组/列表:
- 创建时将线程添加到列表中
- 使用
ThreadGroup
管理线程
以下代码将使用threadgroop
ap
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* synchronized block - learn,
*
* @author eric
* @date Apr 20, 2015 1:37:11 PM
*/
public class SyncBlockLearn {
private static final int TD_COUNT = 5; // thread count
private static final int ROUND_PER_THREAD = 100; // round for each thread,
private static final long INC_DELAY = 10; // delay of each increase,
// sync block test,
@Test
public void syncBlockTest() throws InterruptedException {
Counter ct = new Counter();
ThreadGroup tg = new ThreadGroup("runner");
for (int i = 0; i < TD_COUNT; i++) {
new Thread(tg, ct, "t-" + i).start();
}
Thread[] tArr = new Thread[TD_COUNT];
tg.enumerate(tArr); // get threads,
// wait all runner to finish,
for (Thread t : tArr) {
t.join();
}
System.out.printf("\nfinal count: %d\n", ct.getCount());
Assert.assertEquals(ct.getCount(), TD_COUNT * ROUND_PER_THREAD);
}
static class Counter implements Runnable {
private final Object lkOn = new Object(); // the object to lock on,
private int count = 0;
@Override
public void run() {
System.out.printf("[%s] begin\n", Thread.currentThread().getName());
for (int i = 0; i < ROUND_PER_THREAD; i++) {
synchronized (lkOn) {
System.out.printf("[%s] [%d] inc to: %d\n", Thread.currentThread().getName(), i, ++count);
}
try {
Thread.sleep(INC_DELAY); // wait a while,
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("[%s] end\n", Thread.currentThread().getName());
}
public int getCount() {
return count;
}
}
}
public static void waitForThreadsToFinish(Thread... threads) {
try {
for (Thread thread : threads) {
thread.join();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}