2
\$\begingroup\$

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:

  1. Is there any better way of achieving such functionality?

  2. 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?

asked May 15, 2020 at 18:09
\$\endgroup\$
3
  • 1
    \$\begingroup\$ As for #2: Beware that a listener is nothing more than an object instance that has one or more methods that get called by the object instance that it has been passed to. In principle, a listener does not have to do any multithreading: the code that is run by the listener is generally run in the thread of the method that calls it. And for #1, yes, we use java.util.concurrent. If you're doing locking yourself, you're likely reinventing some threaded wheel. \$\endgroup\$ Commented May 15, 2020 at 23:12
  • \$\begingroup\$ @MaartenBodewes, so, for example, what's the best way of constantly checking if a variable "changes" to trigger some kind of action? \$\endgroup\$ Commented May 15, 2020 at 23:31
  • \$\begingroup\$ What you're probably looking for is a "Monitor". Although java.util.concurrent doesn't have a Monitor class it does have, for instance, ReentrantLock, see here for a (seemingly good) explanation. \$\endgroup\$ Commented May 16, 2020 at 0:07

1 Answer 1

2
\$\begingroup\$

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 = "";
}

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.

answered May 16, 2020 at 18:42
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.