Java中的线程同步

4

我正在实现Java的Runnable接口进行多线程编程。我有一些线程,假设有n个。每个线程都有自己的生命周期。我想等待所有线程的生命周期结束。比如下面这种情况:

for(int i = 0; i< k;i++){
 Thread thread1 = new Thread(new xyz())
 Thread thread2 = new Thread(new abc())
 Thread thread3 = new Thread(new mno())
 thread1.start();
 thread2.start();
 thread3.start();
}

我正在执行以下操作以进行同步。 我不知道是否正确。 请告诉我该如何做? 是否有任何方法可以检查我的线程程序是否正常工作?

          if(thread2.isAlive())
                try {
                    thread2.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            if(thread1.isAlive())
                    try {
                        thread1.join();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            if(thread3.isAlive())
                try {
                        thread3.join();
                } catch (InterruptedException e) {
                e.printStackTrace();
                    }   
5个回答

8
你可以将你的Runnables添加到ExecutorService中,然后调用shutdown/awaitTermination,它们会在所有任务完成后返回。javadoc中有一些示例 - 简而言之,你需要编写类似以下内容的代码:
ExecutorService executor = Executors.newFixedThreadPool(3);

executor.submit(runnable1);
executor.submit(runnable2);
executor.submit(runnable3);

executor.shutdown();
boolean allRunnableAreDone = executor.awaitTermination(60, TimeUnit.SECONDS);

// This line is reached once all runnables have finished their job
// or the 60 second timeout has expired

1
检查awaitTermination的返回值并循环执行是个好主意,以防它花费的时间超过你指定的时间。 - OldCurmudgeon
1
或者调用awaitTermination(Long.MAX_VALUE, ...)而不是只等待60秒。 - Gray

4

虽然来自@assylias的ExecutorService答案不错,但这里提供有关join()的更多信息。

您在join()之前不需要测试isAlive()Thread.join()代码已经执行了该操作。 这是那里代码的摘录:

while (isAlive()) {
    wait(0);
}

所以你需要做的就是使用线程加入:
   try {
       thread2.join();
       thread1.join();
       thread3.join();
   } catch (InterruptedException e) {
       // always a good pattern
       Thread.currentThread().interrupt();
       e.printStackTrace();
   }

我不知道这个。这似乎是最简单的。 - Denys Séguret

2
作为一种简单的解决方案,您可以将所有线程放入一个列表中,在它们启动后调用join:
List<Thread> threads = new ArrayList<>();
for(int i = 0; i< k;i++)
{
  //create threads
  Thread thread1 = new Thread(new xyz());
  Thread thread2 = new Thread(new abc());
  Thread thread3 = new Thread(new mno());

  //store threads
  threads.add(thread1);
  threads.add(thread2);
  threads.add(thread3);

  //start threads
  thread1.start();
  thread2.start();
  thread3.start();
}

//join all threads
for(Thread t : threads)
   t.join();

//You are here after all threads have terminated

1

1

join() 方法并不是在一个线程上等待,而是在一个锁对象上等待。等待线程必须调用 lockObject.join(),工作线程在完成时必须调用 lockObject.notify()。等待线程将被通知并可以继续其工作。您还需要在这些调用周围使用 synchronize 块。

我也推荐像assylias提到的Executor,它比自己实现这种行为要容易得多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接