Please note (as others have pointed out) that you must use the same object to lock / sync in both threads.
If you want your main thread to continue immediately after calling notify , you should temporarily abandon the lock. Otherwise, wait will be called only after the secondary thread leaves the synchronized block. And it is never recommended to keep the lock in a long calculation!
One way to achieve this is to use wait(int) to block instead of sleep , because wait temporarily temporarily blocks synchronization:
public class Tester { private static final Object lock = new Object(); public static void main(String[] args) { Thread t = new Thread(new MyRunnable()); t.start(); synchronized (lock) { try { System.out.println("wating for t to complete"); lock.wait(); System.out.println("wait over"); } catch (InterruptedException e) { e.printStackTrace(); } } } static class MyRunnable implements Runnable { public void run() { System.out.println("entering run method"); synchronized (lock) { System.out.println("entering syncronised block"); lock.notify(); try { lock.wait(1000);
However, the use of these low-level primitives can be very error prone, and I will not discourage their use. Instead, I suggest you use the high level Java primitives for this. For example, you can use CountDownLatch , which allows one thread to wait until the other threads go to zero:
import java.util.concurrent.*; public class TesterC { private static final CountDownLatch latch = new CountDownLatch(1); public static void main(String[] args) { Thread t = new Thread(new MyRunnable()); t.start(); System.out.println("wating for t to complete"); try { latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("wait over"); } static class MyRunnable implements Runnable { public void run() { System.out.println("entering run method"); try { latch.countDown(); Thread.sleep(1000); } catch (InterruptedException ex) { System.out.println("got interrupted"); } System.out.println("leaving run method"); } } }
Here you do not need to synchronize anything, the latch does everything for you. There are many other primitives you can use: semaphores, exchangers, threads with security, etc. Explorer java.util.concurrent .
Perhaps even a better solution is to use a higher-level API, such as Akka . There you work with Actors or Transactional Programming Memory , which can easily compile and save you most concurrency problems.
Petr pudlรกk
source share