A sleeping thread until an event is visited in another thread from another class

I have an application that starts 2 threads, the first starts another class to do some processing, which in turn starts the third class to do even more processing. The second thread in the main class must wait for any event in the third class to finish before it does its job. How can this be achieved?

I tried to implement wait / notify to share a lock object between two threads, but technically this will not work as I found the hard way. Can I use lock between classes? Note that an instance of the third class is declared in the 1st class and passed as a parameter to the second class. I also tried to create a boolean in the 3rd class, which reports when the event is completed, and then polling the 2nd thread until this value is true. It worked, but not very desirable. Is there also an actionListner better approach to this problem?

+4
source share
5 answers

What problem did you encounter? As you describe it, it should work. For example, you could implement 2 methods for the 3rd class, which save the flag, which is checked from one and set from another class, using the instance as a lock:

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: printed from memory, not verified using Java compilation)

In principle, this. pending and notifyAll is not required, I find it clearer to include them in this situation.

+9
source

Use a CountDownLatch with an initial value of 1.

Make a 3rd class call countDown () after processing is complete. The calling thread can then call wait (), which will block until processing is complete.

+3
source

The task you are solving can be easily solved either using the ActionListener , or using the general Queue .

Just select any blocking queue that blocks the user until something appears in the queue. Simple, clear and tested.

If you need more, take a look at projects like http://akkasource.org/ or http://jcp.org/en/jsr/detail?id=166 (will be included by default in Java 7).

+3
source

You want to use a counting semaphore. Condition variables are used to schedule flows within the monitor. This is not what you are trying to do.

You create a counting semaphore and set the counter 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 whether the processing does. When it is completed, it will increment the counter to 1 by calling s.release() .

To block the thread until processing is complete, you call s.aquire() . This call will block your other thread until the processor calls s.release() .

This is the simplest solution.

Btw, s.aquire() and s.release() are thread safe, so you do not need to use the synchronize keyword. Topics can share semaphore references and call its methods without blocking.

UPDATE:

I am going to answer your comment here, and not make a new comment.

Yes, in your case, the wait () / notify () solution is similar to using a semaphore. To rewrite the rsp solution using a semaphore, it would look like this:

 java.util.concurrent.Semaphore s = new java.util.concurrent.Semaphore(0); public setDone() { s.release(); } public waitUntilDone() { s.aquire(); } 

This is much simpler and you do not need unnecessary locking (note that I removed the synchronized keyword from the decs method.).

There are two differences between state variables (wait () / notify ()) and semaphores.

Difference # 1: notify () calls may be lost, release () calls are never lost

The first difference is that notify () calls are lost if there is no waiting thread through the wait () call. The work around is to check the state before calling wait (). Basically, we need to remember that notify () is called with a shared variable, so we do not accidentally call wait () after the worker calls notify (), or we are stuck. Counting semaphores works regardless of the order in which the receive () and release () functions are called, since they support the count internally.

Difference # 2: calls to wait () automatically release the lock, calls acquire () do not

Some reference data will help here. In your program, boolean done = false; variable is a condition, but it is not a condition variable. I know confusing terminology. A condition variable is a variable that has wait () and notify () operations. Each object in Java has a condition variable hidden inside and a corresponding lock.

All condition variables are associated with a lock. You must acquire a lock before you can call wait () and notify () (you will get an exception at runtime, if you don't, try). Once the lock is received, calls to wait () will automatically release the lock, allowing another thread inside the monitor, possibly calling notify (). Sometimes this is exactly what you want, and trying to mimic this behavior with semaphores will be a lot harder.

Note. I use the academic definition of a monitor, which is completely different from the definition of a Java monitor.

+1
source

I think join() operation is suitable for this purpose

Illustration:

Let's say you have 2 threads

thead1 -> The thread to wait.

thread2 -> thread on which thread1 should wait.

then in the thread1 code, in the place where you want to wait, write

 thread2.join() 

Hope this helps!

0
source

Source: https://habr.com/ru/post/1309183/


All Articles