如何知道其他线程是否已完成?
我有一个对象,其方法名为 ,它启动三个线程。StartDownload()
当每个线程完成执行时,如何收到通知?
有没有办法知道一个(或全部)线程是否已完成或仍在执行?
我有一个对象,其方法名为 ,它启动三个线程。StartDownload()
当每个线程完成执行时,如何收到通知?
有没有办法知道一个(或全部)线程是否已完成或仍在执行?
您可以通过多种方式执行此操作:
如何实现想法#5?好吧,一种方法是首先创建一个接口:
public interface ThreadCompleteListener {
void notifyOfThreadComplete(final Thread thread);
}
然后创建以下类:
public abstract class NotifyingThread extends Thread {
private final Set<ThreadCompleteListener> listeners
= new CopyOnWriteArraySet<ThreadCompleteListener>();
public final void addListener(final ThreadCompleteListener listener) {
listeners.add(listener);
}
public final void removeListener(final ThreadCompleteListener listener) {
listeners.remove(listener);
}
private final void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.notifyOfThreadComplete(this);
}
}
@Override
public final void run() {
try {
doRun();
} finally {
notifyListeners();
}
}
public abstract void doRun();
}
然后你的每个线程都会扩展,而不是实现它将实现。因此,当他们完成时,他们会自动通知任何等待通知的人。NotifyingThread
run()
doRun()
最后,在你的主类中 - 启动所有线程(或至少等待通知的对象)的类 - 将该类修改为并在创建每个线程后立即将自身添加到侦听器列表中:implement ThreadCompleteListener
NotifyingThread thread1 = new OneOfYourThreads();
thread1.addListener(this); // add ourselves as a listener
thread1.start(); // Start the Thread
然后,当每个 Thread 退出时,将使用刚刚完成(或崩溃)的 Thread 实例调用您的方法。notifyOfThreadComplete
请注意,更好的是 to 而不是 for,因为在新代码中通常不鼓励扩展 Thread。但是我正在编码你的问题。如果将类更改为实现,则必须更改一些管理 Threads 的代码,这非常简单。implements Runnable
extends Thread
NotifyingThread
NotifyingThread
Runnable
public class Downloader {
private CyclicBarrier barrier;
private final static int NUMBER_OF_DOWNLOADING_THREADS;
private DownloadingThread extends Thread {
private final String url;
public DownloadingThread(String url) {
super();
this.url = url;
}
@Override
public void run() {
barrier.await(); // label1
download(url);
barrier.await(); // label2
}
}
public void startDownload() {
// plus one for the main thread of execution
barrier = new CyclicBarrier(NUMBER_OF_DOWNLOADING_THREADS + 1); // label0
for (int i = 0; i < NUMBER_OF_DOWNLOADING_THREADS; i++) {
new DownloadingThread("http://www.flickr.com/someUser/pic" + i + ".jpg").start();
}
barrier.await(); // label3
displayMessage("Please wait...");
barrier.await(); // label4
displayMessage("Finished");
}
}
label0 - 创建循环屏障,其中的参与方数等于执行线程数加上执行主线程(其中 startDownload() 正在执行)
标签 1 - 第 n 个 下载线程进入等候室
标签3 - NUMBER_OF_DOWNLOADING_THREADS已进入候诊室。执行的主线程释放它们,使其在或多或少相同的时间开始执行下载作业
标签 4 - 执行的主线程进入等候室。这是代码中“最难理解”的部分。哪个线程将第二次进入等候室并不重要。重要的是,无论最后进入房间的线程如何,都要确保所有其他下载线程都已完成其下载作业。
标签 2 - 第 n 个 DownloadingThread 已完成下载作业并进入等候室。如果它是最后一个,即已经NUMBER_OF_DOWNLOADING_THREADS输入它,包括执行的主线程,则只有当所有其他线程都完成下载时,主线程才会继续执行。