vico
vico

Reputation: 18191

How to tell main thread that part of thread job is done

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

Answers (3)

SamYonnou
SamYonnou

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

Ralf H
Ralf H

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

Zim-Zam O'Pootertoot
Zim-Zam O'Pootertoot

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

Related Questions