我有一个激活2个线程的应用程序,第1个启动另一个类来进行一些处理,然后启动第3个类来进行更多处理。主类中的第二个线程应该等到第三个类中的某个事件在执行其作业之前完成。怎么能实现这一目标?
我曾尝试实现一个wait / notify来共享两个线程之间的锁定对象,但从技术上讲,这不会起作用,因为我发现了困难。我可以在课堂之间分享锁吗?注意,第3个类的实例在第1个类中声明,并作为参数传递给第2个类。此外,我尝试在第3类中创建布尔值,告诉事件何时完成然后轮询第2个线程,直到该值为真。这有效,但不是很理想。 actionListner也是解决这个问题的更好方法吗?
答案 0 :(得分:11)
你遇到了什么问题?正如你所描述的那样,它应该有效。例如,您可以在第3个类上实现2个方法,这些方法保留一个标志,该标志从一个中检查,并使用该实例作为锁从另一个类中设置:
boolean done = false;
public synchronized setDone() {
done = true;
this.notifyAll();
}
public synchronized waitUntilDone() {
while (!done) {
try {
this.wait();
} catch (InterruptedException ignore) {
// log.debug("interrupted: " + ignore.getMessage());
}
}
}
(注意:从内存中输入,不使用Java编译检查)
原则上,在不需要等待和notifyAll之前this.
,我发现在这种情况下将它们包括在内更清楚。
答案 1 :(得分:3)
使用初始值为1的CountDownLatch。
处理完成后,让第3类调用countDown()。然后调用线程可以调用await(),它将阻塞直到处理完成。
答案 2 :(得分:3)
使用ActionListener
或使用共享Queue
可轻松解决您正在解决的问题。
选择阻止消费者的任何阻塞队列,直到队列中出现问题为止。简单,清晰且经过验证。
如果您需要更多内容,请查看http://akkasource.org/或http://jcp.org/en/jsr/detail?id=166等项目(默认情况下将包含在Java 7中)。
答案 3 :(得分:3)
您想使用计数信号量。条件变量用于调度监视器内的线程。这不是你想要做的。
您创建一个计数信号量并将计数设置为零
// create a counting semaphore with an initial count of zero
java.util.concurrent.Semaphore s = new java.util.concurrent.Semaphore(0);
您将信号量传递给您的类处理。完成后,通过调用s.release()
将计数增加到1。
要阻止线程直到处理器完成,请调用s.aquire()
。该调用将导致您的其他线程阻塞,直到处理器调用s.release()
。
这是最简单的解决方案。
顺便说一句,s.aquire()
和s.release()
是线程安全的,因此您不需要使用synchronize关键字。线程可以共享对信号量的引用,并在不锁定的情况下调用其方法。
更新:
我将在此处回复您的评论,而不是发表新评论。
是的,在您的情况下,wait()/ notify()解决方案类似于使用信号量。要使用信号量重写rsp的解决方案,它看起来像:
java.util.concurrent.Semaphore s = new java.util.concurrent.Semaphore(0);
public setDone() {
s.release();
}
public waitUntilDone() {
s.aquire();
}
它更简单,你不需要一个不必要的锁(注意我从方法decs中删除了synchronized关键字。)。
条件变量(wait()/ notify())和信号量之间存在2个差异。
差异#1:对notify()的调用可能会丢失,对release()的调用永远不会丢失
第一个区别是,如果没有线程通过调用wait()等待,则对notify()的调用将丢失。解决方法是在调用wait()之前检查条件。基本上,我们需要记住notify()是使用共享变量调用的,所以我们不会在worker调用notify()之后不小心调用wait(),否则我们会死锁。无论调用acquire()和release()的顺序如何,计数信号量都有效,因为它们在内部保持计数。
区别#2:调用wait()自动释放锁,调用acquire()不
一些背景信息在这里会有所帮助。在您的计划中boolean done = false;
变量是条件,但它不是条件变量。令人困惑的术语,我知道。条件变量是具有操作wait()和notify()的变量。 Java中的每个对象都有一个隐藏在里面的条件变量和一个相应的锁。
所有条件变量都与锁相关联。您必须先获取锁,然后才能调用wait()和notify()(如果不这样,您将获得运行时异常,请尝试)。获取锁后,调用wait()会自动释放锁,允许监视器内的另一个线程可能调用notify()。有时候,这正是你想要的,尝试用信号量模拟这种行为将会复杂得多。
注意:我使用的是监视器的学术定义,它完全不同于监视器的Java定义。
答案 4 :(得分:0)
我认为join()
操作符合此目的
插图:
假设您有2个帖子
thead1 - >需要等待的线程。
thread2 - > thread1必须等待的线程。
然后在thread1的代码中,在你想等待的地方,写下
thread2.join()
希望这有帮助!