Example using Object lock synchronized blocks Here's my attempt at trying to understand synchronized() blocks using an Object lock, using wait() and notify():


import java.util.Scanner;

public class SyncTest {

    private Scanner scanner;
    private Object lock;
    private volatile String string;

    public SyncTest() {
        scanner = new Scanner(System.in);
        lock = new Object();
        string = "";
    }

    public void start() {

        //This thread will wait until the other thread notifies it.
        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    synchronized (lock) {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("String changed.");
                }
            }
        });
        t1.start();

        //This thread will notify Thread 1 if a condition is met.
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    if (!string.isEmpty()) {
                        synchronized (lock) {
                            lock.notify();
                        }
                        string = "";
                    }
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        t2.start();

        //This is just a dummy thread to modify the string data.
        Thread t3 = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    string = scanner.nextLine();
                }
            }
        });
        t3.start();
    }

    public static void main(String[] args) {
        new SyncTest().start();
    }

}


Couple questions:


Is there any better way of achieving such functionality?
Is this how listeners work? How are they so efficient at listening to events? I mean, if I don't add the 200ms delay in t2 execution, the thread will consume a lot of processing power, so, how can I create a listener behavior?
It does look sound to me with one exception that you need to be aware of, as far as I can see:
if (!string.isEmpty()) {
    synchronized (lock) {
        lock.notify();
    }
    string = &quot;&quot;;
}

The moment you set string to a new value, the first thread might not have visited the variable at this point. You can see that when outputting string in both threads. This is only important if thread #1 is going to do processing on the value.
Additionally, because of the Thread.sleep(200); you might miss input lines because string value might have changed an unidentified number of times during this period.


I mean, if I don't add the 200ms delay in t2 execution, the thread will consume a lot of processing power, so, how can I create a listener behavior?

The same way you did between #2 and #1, notify #2 from #3.

To fix these issues, you want to use something like a BlockingQueue. Thread #3 pushes the line to the Queue, thread #2 dequeues the next value and notifies #1. Or, #2 pushes it to a second Queue for #1.