java 休眠一个线程,直到一个事件在另一个类的另一个线程中参与
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2793615/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sleep a thread until an event is attended in another thread from a different class
提问by Afro Genius
I have an application that fires 2 threads, the 1st launches another class to do some processing which in turn launches a 3rd class to do yet more processing. The 2nd thread in the main class should wait until some event in the 3rd class completes before it performs its job. How can this be achieved?
我有一个触发 2 个线程的应用程序,第一个启动另一个类来做一些处理,然后启动第三个类来做更多的处理。主类中的第二个线程应该等到第三个类中的某个事件完成后才能执行其工作。如何做到这一点?
I had tried implementing a wait/notify to share a lock object between the two threads but technically this will not work as I found the hard way. Can I share a lock between classes? Note, an instance of the 3rd class is declared in the 1st class and passed as parameter to the 2nd class. Also I tried creating boolean value in 3rd class that tells when event is complete then poll 2nd thread till this value is true. This worked but is not very desirable. Also is actionListner a better approach to this problem?
我曾尝试实现一个等待/通知以在两个线程之间共享一个锁定对象,但从技术上讲,这行不通,因为我发现了困难的方法。我可以在班级之间共享锁吗?请注意,第三个类的实例在第一个类中声明并作为参数传递给第二个类。我还尝试在第三个类中创建布尔值,告诉事件何时完成,然后轮询第二个线程,直到该值为真。这有效但不是很理想。actionListner 也是解决这个问题的更好方法吗?
回答by rsp
What problem did you encounter? As you describe it, it should work. For instance you could implement 2 methods on the 3rd class which keep a flag which is checked from the one and set from the other class using the instance as lock:
你遇到了什么问题?正如你所描述的,它应该可以工作。例如,您可以在第 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());
}
}
}
(note: typed from memory, not checked using a Java compile)
(注意:从内存中输入,未使用 Java 编译检查)
In principle the this.before the wait and notifyAll is not needed, I find it clearer to include them in this situation.
原则上不this.需要 wait 和 notifyAll 之前,我发现将它们包括在这种情况下会更清楚。
回答by rhys keepence
Use a CountDownLatch with an initial value of 1.
使用初始值为 1 的 CountDownLatch。
Make the 3rd class call countDown() once processing is complete. The calling thread can then call await(), which will block until processing is complete.
处理完成后,进行第三类调用 countDown()。然后调用线程可以调用 await(),它会阻塞直到处理完成。
回答by mindas
The problem you are solving can easily be solved by either using ActionListeneror using a shared Queue.
您正在解决的问题可以通过使用ActionListener或使用共享Queue.
Just pick any blocking queue which would block consumer until something comes up in the queue. Simple, clear and proven.
只需选择任何会阻塞消费者的阻塞队列,直到队列中出现某些内容。简单、清晰且经过验证。
If you need more, look at projects like http://akkasource.org/or http://jcp.org/en/jsr/detail?id=166(will be included by default in Java 7).
如果您需要更多,请查看类似http://akkasource.org/或http://jcp.org/en/jsr/detail?id=166(默认包含在 Java 7 中)的项目。
回答by Jay
You want to use a counting semaphore. Condition variables are meant for scheduling threads inside a monitor. This is not what your trying to do.
您想使用计数信号量。条件变量用于在监视器内调度线程。这不是你想要做的。
You create a counting semaphore and set the count to zero
您创建一个计数信号量并将计数设置为零
// create a counting semaphore with an initial count of zero
java.util.concurrent.Semaphore s = new java.util.concurrent.Semaphore(0);
You pass the semaphore to your class the does the processing. When it is finished, it increasing the count to 1 by calling s.release().
您将信号量传递给您的班级进行处理。完成后,它通过调用将计数增加到 1 s.release()。
To block a thread until the processor is finished, you call s.aquire(). That call will cause your other thread to block until the processor calls s.release().
要阻塞线程直到处理器完成,您可以调用s.aquire(). 该调用将导致您的另一个线程阻塞,直到处理器调用s.release()。
This is the simplest solution.
这是最简单的解决方案。
Btw, s.aquire()and s.release()are thread safe, so you don't need to use the synchronize keyword. Threads can share references to a semaphore and call its methods without locking.
顺便说一句,s.aquire()并且s.release()是线程安全的,因此您不需要使用同步关键字。线程可以共享对信号量的引用并在不加锁的情况下调用其方法。
UPDATE:
更新:
I'm going to respond to your comment here instead of making a new comment.
我将在这里回复您的评论,而不是发表新评论。
Yes, in your case a wait()/notify() solution is similar to using a semaphore. To rewrite rsp's solution with a semaphore, it would look like:
是的,就您而言,wait()/notify() 解决方案类似于使用信号量。用信号量重写 rsp 的解决方案,它看起来像:
java.util.concurrent.Semaphore s = new java.util.concurrent.Semaphore(0);
public setDone() {
s.release();
}
public waitUntilDone() {
s.aquire();
}
It is much simpler and you don't need an unnecessary lock (notice i removed the synchronized keyword from the method decs.).
它更简单,您不需要不必要的锁(注意我从方法 decs. 中删除了 synchronized 关键字)。
There are 2 differences between condition variables (wait()/notify()) and semaphores.
条件变量(wait()/notify())和信号量之间有两个区别。
Difference #1: calls to notify() may be lost, calls to release() are never lost
区别#1:对notify() 的调用可能会丢失,对release() 的调用永远不会丢失
The first difference is that calls to notify() are are lost if there is no thread waiting via a call to wait(). The work around is to check the condition before calling wait(). Basically, we need to remember that notify() was called with a shared variable so we don't accidentally call wait() after the worker calls notify(), or else we deadlock. Counting semaphores work no matter the order in which acquire() and release() are called because they maintain a count inside.
第一个区别是,如果没有线程通过调用 wait() 等待,则对 notify() 的调用将丢失。解决方法是在调用 wait() 之前检查条件。基本上,我们需要记住notify() 是使用共享变量调用的,所以我们不会在worker 调用notify() 后意外调用wait(),否则我们会死锁。无论调用acquire() 和release() 的顺序如何,计数信号量都可以工作,因为它们在内部维护一个计数。
Difference #2: calls to wait() automatically release a lock, calls to acquire() do not
区别#2:调用wait()自动释放锁,调用acquire()不会
Some background information will help here. In your program the boolean done = false;variable is the condition, but it isn't the condition variable. Confusing terminology, I know. The condition variable is the variable that has operations wait() and notify(). Every object in Java has a condition variable hidden inside and a corresponding lock.
一些背景信息在这里会有所帮助。在您的程序中,boolean done = false;变量是条件,但不是条件变量。令人困惑的术语,我知道。条件变量是具有操作wait() 和notify() 的变量。Java 中的每个对象都有一个隐藏在里面的条件变量和一个对应的锁。
All condition variables are associated with a lock. You must acquire the lock before you can call wait() and notify() (you will get a runtime exception if you don't, try it). Once the lock is acquired, calls to wait() automatically release the lock, allowing another thread inside the monitor to possibly call notify(). Sometimes, this is exactly what you want, and trying to simulate this behavior with semaphores will be much more complicated.
所有条件变量都与锁相关联。您必须先获取锁,然后才能调用 wait() 和 notify()(如果不这样做,您将收到运行时异常,请尝试)。一旦获得锁,调用wait() 会自动释放锁,允许监视器内的另一个线程可能调用notify()。有时,这正是您想要的,而尝试用信号量模拟这种行为会复杂得多。
Note: I'm using the academic definition of monitor which differs entirely from the Java definition of a monitor.
注意:我使用的是监视器的学术定义,它与监视器的 Java 定义完全不同。
回答by Sagar Nayak
I think join()operation would suit this purpose
我认为join()操作适合这个目的
Illustration:
插图:
Lets say you have 2 threads
假设您有 2 个线程
thead1 -> The thread that needs to wait.
thead1 -> 需要等待的线程。
thread2 -> The thread on which thread1 has to wait.
thread2 -> thread1 必须等待的线程。
then in the code of thread1, at the place where you wish to wait, write
然后在thread1的代码中,在你要等待的地方,写
thread2.join()
Hope this helps!
希望这可以帮助!

