等待所有线程在java中完成其工作

等待所有线程在java中完成其工作,java,multithreading,wait,Java,Multithreading,Wait,我正在编写一个应用程序,它有5个线程,可以同时从web获取一些信息,并在缓冲区类中填充5个不同的字段。 我需要验证缓冲区数据,并在所有线程完成其工作后将其存储在数据库中。 我如何才能做到这一点(当所有线程完成其工作时得到警报) 您可以添加到线程。连接将阻塞,直到线程完成 for (Thread thread : threads) { thread.join(); } 请注意,join抛出一个InterruptedException。如果发生这种情况,您必须决定要做什么(例如,尝试取消其

我正在编写一个应用程序,它有5个线程,可以同时从web获取一些信息,并在缓冲区类中填充5个不同的字段。
我需要验证缓冲区数据,并在所有线程完成其工作后将其存储在数据库中。
我如何才能做到这一点(当所有线程完成其工作时得到警报)

您可以添加到线程。连接将阻塞,直到线程完成

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();
            }
        }