Reputation: 18191
Is it true that notify works only after thread is finished? In code below I can't get notification until I comment while (true). How to tell main thread that part of thread job is done?
public class ThreadMain {
public Thread reader;
private class SerialReader implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(3000);
synchronized(this) {
System.out.println("notifying");
notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
synchronized(d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
Upvotes: 0
Views: 160
Reputation: 2068
As user oddparity noted in the comments, you are calling wait()
and notify()
on different objects. A possible fix for this would be to make your SerialReader
extend Thread
rather than implement Runnable
and then assigning reader
to be a new instance of the SerialReader
directly. :
public class ThreadMain {
public Thread reader;
private class SerialReader extends Thread {
public void run() {
while (true) {
try {
Thread.sleep(3000);
synchronized(this) {
System.out.println("notifying");
notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new SerialReader();
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
synchronized(d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
If you want to use Runnable
with wait()
/notify()
you can do it this way :
public class ThreadMain {
public Thread reader;
private class SerialReader implements Runnable {
public void run() {
Thread thisThread = Thread.currentThread();
while (true) {
try {
Thread.sleep(3000);
synchronized (thisThread) {
System.out.println("notifying");
thisThread.notify();
System.out.println("notifying done");
}
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String[] args) {
ThreadMain d = new ThreadMain();
d.reader.start();
synchronized (d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
Upvotes: 0
Reputation: 1474
If you want to be notified when the Thread t
completes, call t.join()
in the calling Thread. This will block until t
has finished its Runnable
.
Upvotes: 0
Reputation: 18148
You should try to avoid using wait
and notify
with the newer versions of Java, as they're difficult to get right. Try using something like a BlockingQueue
instead
public class ThreadMain {
public final BlockingQueue<Boolean> queue = new LinkedBlockingQueue<>();
private class SerialReader implements Runnable {
public void run() {
while (true) {
try {
Thread.sleep(3000);
System.out.println("notifying");
queue.offer(Boolean.TRUE);
System.out.println("notifying done");
} catch (Exception e) {
System.out.println(e);
}
}
}
}
ThreadMain() {
reader = new Thread(new SerialReader());
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
try {
d.queue.take(); // block until something is put in the queue
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
}
Upvotes: 1