The most complicated thing in the world to understand is concurrency. Not even Einstein's General Theory of Relativity comes close. Here is an interesting gem that I got from a newsletter quite some time ago. I found the puzzle incredibly interesting and it convinced me to NEVER EVER EVER EVER:
- Assume I understand concurrency.
- Use the old core Threading stuff rather than the new modern concurrency frameworks (i.e. Threading pools, etc.).
- Assume I understand concurrency.
- Skip testing threaded applications - because I'm clever, it makes sense... and besides I understand concurrency.
- Assume I understand concurrency.
Look at the following Rorotika-inspired class and tell me what happens. Keep careful track of all the delays.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Worker extends Thread { | |
private volatile boolean quittingTime = false; | |
public void run() { | |
while (!quittingTime) { | |
pretendToWork(); | |
} | |
System.out.println("Beer is good"); | |
} | |
private void pretendToWork() { | |
try { | |
System.out.println("..working!"); | |
Thread.sleep(300); // Sleeping on the job? | |
} catch (InterruptedException e) { | |
} | |
} | |
// It's quitting time, wait for worker - | |
// Called by good boss | |
synchronized void quit() throws InterruptedException { | |
System.out.println("Ok guys! Have a beer!"); | |
quittingTime = true; | |
join(); | |
} | |
// Rescind quitting time - Called by evil boss | |
synchronized void keepWorking() { | |
System.out.println("Work! Dammit! I don't "+ | |
"pay you to drink beer!"); | |
quittingTime = false; | |
} | |
public static void main(String[] args) | |
throws InterruptedException { | |
final Worker worker = new Worker(); | |
worker.start(); | |
Timer t = new Timer(true); // Daemon thread | |
t.schedule(new TimerTask() { | |
public void run() { | |
worker.keepWorking(); | |
} | |
}, 500); | |
Thread.sleep(400); | |
worker.quit(); | |
} | |
} |