Skip to content

Instantly share code, notes, and snippets.

@sshark
Last active February 18, 2024 17:04
Show Gist options
  • Save sshark/7d29a51e44d550cbb5f0c920744d21a1 to your computer and use it in GitHub Desktop.
Save sshark/7d29a51e44d550cbb5f0c920744d21a1 to your computer and use it in GitHub Desktop.
Controlled threads execution
package th.lim;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* Suppose we have the following code:
*
* class Foo {
* void first() {...}
* void second() {...}
* void third() {...}
* }
*
* The same instance of Foo will be passed to three different threads. Thread
* A will call first(), Thread B will call second(), and Thread C will call
* third(). Design a mechanism to ensure that first() is called before
* second() and second() is called before third().
*/
public class Foo {
Object lock = new Object();
int action = 1;
void first() {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + " -> first");
action++;
// must be notifyAll() instead of notify(). Otherwise, it might hang if
// task t3 gets notified instead
lock.notifyAll();
}
}
void second() {
synchronized (lock) {
while (action != 2) {
try {
lock.wait();
} catch (Exception e) {
}
}
System.out.println(Thread.currentThread().getName() + " -> second");
action++;
lock.notify(); // notify is sufficient because there is only 1 thread waiting
}
}
void third() {
synchronized (lock) {
while (action != 3) {
try {
lock.wait();
} catch (Exception e) {
}
}
System.out.println(Thread.currentThread().getName() + " -> third");
}
}
public static void main(String[] args) {
Foo foo = new Foo();
Runnable t1 = foo::first;
Runnable t2 = foo::second;
Runnable t3 = foo::third;
ExecutorService es = Executors.newCachedThreadPool();
es.submit(t3);
es.submit(t2);
es.submit(t1);
es.shutdown();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment