有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何等待多个线程完成?

什么是一种简单地等待所有线程进程完成的方法?例如,假设我有:

public class DoSomethingInAThread implements Runnable{

    public static void main(String[] args) {
        for (int n=0; n<1000; n++) {
            Thread t = new Thread(new DoSomethingInAThread());
            t.start();
        }
        // wait for all threads' run() methods to complete before continuing
    }

    public void run() {
        // do something here
    }


}

我如何修改它,使main()方法在注释处暂停,直到所有线程的run()方法退出?谢谢


共 (6) 个答案

  1. # 1 楼答案

    完全避免使用Thread类,而是使用java中提供的高级抽象。util。同时发生

    ExecutorService类提供的method invokeAll似乎正是您想要的

  2. # 2 楼答案

    一种方法是制作ListThread线程,创建并启动每个线程,同时将其添加到列表中。一旦所有东西都启动了,循环浏览列表,并对每个列表调用join()。不管线程以什么顺序完成执行,您需要知道的是,当第二个循环完成执行时,每个线程都将完成

    更好的方法是使用ExecutorService及其相关方法:

    List<Callable> callables = ... // assemble list of Callables here
                                   // Like Runnable but can return a value
    ExecutorService execSvc = Executors.newCachedThreadPool();
    List<Future<?>> results = execSvc.invokeAll(callables);
    // Note: You may not care about the return values, in which case don't
    //       bother saving them
    

    使用ExecutorService(以及Java5的concurrency utilities中的所有新东西)是非常灵活的,上面的例子几乎没有触及表面

  3. # 3 楼答案

    考虑使用^ {CD1>}。在javadocs中的示例

  4. # 4 楼答案

    将所有线程放在一个数组中,启动所有线程,然后创建一个循环

    for(i = 0; i < threads.length; i++)
      threads[i].join();
    

    每个连接都将阻塞,直到相应的线程完成。线程的完成顺序可能与加入它们的顺序不同,但这不是问题:当循环退出时,所有线程都已完成

  5. # 5 楼答案

    可以使用CountDownLatch,而不是join()这是一个旧的API。我已经修改了你的代码如下,以满足你的要求

    import java.util.concurrent.*;
    class DoSomethingInAThread implements Runnable{
        CountDownLatch latch;
        public DoSomethingInAThread(CountDownLatch latch){
            this.latch = latch;
        } 
        public void run() {
            try{
                System.out.println("Do some thing");
                latch.countDown();
            }catch(Exception err){
                err.printStackTrace();
            }
        }
    }
    
    public class CountDownLatchDemo {
        public static void main(String[] args) {
            try{
                CountDownLatch latch = new CountDownLatch(1000);
                for (int n=0; n<1000; n++) {
                    Thread t = new Thread(new DoSomethingInAThread(latch));
                    t.start();
                }
                latch.await();
                System.out.println("In Main thread after completion of 1000 threads");
            }catch(Exception err){
                err.printStackTrace();
            }
        }
    }
    

    解释

    1. CountDownLatch已根据您的要求使用给定的计数1000进行初始化

    2. 每个工作线程DoSomethingInAThread将递减CountDownLatch,该值已在构造函数中传递

    3. 主线程CountDownLatchDemoawait()直到计数变为零。一旦计数变为零,您将在输出中得到下线

      In Main thread after completion of 1000 threads
      

    来自oracle文档页面的更多信息

    public void await()
               throws InterruptedException
    

    Causes the current thread to wait until the latch has counted down to zero, unless the thread is interrupted.

    有关其他选项,请参阅相关SE问题:

    wait until all threads finish their work in java

  6. # 6 楼答案

    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ExecutionException;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    public class DoSomethingInAThread implements Runnable
    {
       public static void main(String[] args) throws ExecutionException, InterruptedException
       {
          //limit the number of actual threads
          int poolSize = 10;
          ExecutorService service = Executors.newFixedThreadPool(poolSize);
          List<Future<Runnable>> futures = new ArrayList<Future<Runnable>>();
    
          for (int n = 0; n < 1000; n++)
          {
             Future f = service.submit(new DoSomethingInAThread());
             futures.add(f);
          }
    
          // wait for all tasks to complete before continuing
          for (Future<Runnable> f : futures)
          {
             f.get();
          }
    
          //shut down the executor service so that this thread can exit
          service.shutdownNow();
       }
    
       public void run()
       {
          // do something here
       }
    }