Java tutorial
public class BestReplacement extends Object { private Thread internalThread; private volatile boolean stopRequested; private BooleanLock suspendRequested; private BooleanLock internalThreadSuspended; public BestReplacement() { stopRequested = false; suspendRequested = new BooleanLock(false); internalThreadSuspended = new BooleanLock(false); Runnable r = new Runnable() { public void run() { try { runWork(); } catch (Exception x) { x.printStackTrace(); } } }; internalThread = new Thread(r); internalThread.start(); } private void runWork() { int count = 0; while (!stopRequested) { try { waitWhileSuspended(); } catch (InterruptedException x) { Thread.currentThread().interrupt(); continue; } System.out.println("Part I - count=" + count); try { Thread.sleep(1000); } catch (InterruptedException x) { Thread.currentThread().interrupt(); } System.out.println("Part II - count=" + count); try { Thread.sleep(1000); } catch (InterruptedException x) { Thread.currentThread().interrupt(); } System.out.println("Part III - count=" + count); count++; } } private void waitWhileSuspended() throws InterruptedException { synchronized (suspendRequested) { if (suspendRequested.isTrue()) { try { internalThreadSuspended.setValue(true); suspendRequested.waitUntilFalse(0); } finally { internalThreadSuspended.setValue(false); } } } } public void suspendRequest() { suspendRequested.setValue(true); } public void resumeRequest() { suspendRequested.setValue(false); } public boolean waitForActualSuspension(long msTimeout) throws InterruptedException { return internalThreadSuspended.waitUntilTrue(msTimeout); } public void stopRequest() { stopRequested = true; internalThread.interrupt(); } public boolean isAlive() { return internalThread.isAlive(); } public static void main(String[] args) { try { BestReplacement br = new BestReplacement(); System.out.println(" just created, br.isAlive()=" + br.isAlive()); Thread.sleep(4200); long startTime = System.currentTimeMillis(); br.suspendRequest(); System.out.println(" just submitted a suspendRequest"); boolean suspensionTookEffect = br.waitForActualSuspension(10000); long stopTime = System.currentTimeMillis(); if (suspensionTookEffect) { System.out.println(" the internal thread took " + (stopTime - startTime) + " ms to notice " + "\n the suspend request and is now " + "suspended."); } else { System.out.println(" the internal thread did not notice " + "the suspend request " + "\n within 10 seconds."); } Thread.sleep(5000); br.resumeRequest(); System.out.println("Submitted a resumeRequest"); Thread.sleep(2200); br.stopRequest(); System.out.println("Submitted a stopRequest"); } catch (InterruptedException x) { // ignore } } } class BooleanLock extends Object { private boolean value; public BooleanLock(boolean initialValue) { value = initialValue; } public BooleanLock() { this(false); } public synchronized void setValue(boolean newValue) { if (newValue != value) { value = newValue; notifyAll(); } } public synchronized boolean waitToSetTrue(long msTimeout) throws InterruptedException { boolean success = waitUntilFalse(msTimeout); if (success) { setValue(true); } return success; } public synchronized boolean waitToSetFalse(long msTimeout) throws InterruptedException { boolean success = waitUntilTrue(msTimeout); if (success) { setValue(false); } return success; } public synchronized boolean isTrue() { return value; } public synchronized boolean isFalse() { return !value; } public synchronized boolean waitUntilTrue(long msTimeout) throws InterruptedException { return waitUntilStateIs(true, msTimeout); } public synchronized boolean waitUntilFalse(long msTimeout) throws InterruptedException { return waitUntilStateIs(false, msTimeout); } public synchronized boolean waitUntilStateIs(boolean state, long msTimeout) throws InterruptedException { if (msTimeout == 0L) { while (value != state) { wait(); } return true; } long endTime = System.currentTimeMillis() + msTimeout; long msRemaining = msTimeout; while ((value != state) && (msRemaining > 0L)) { wait(msRemaining); msRemaining = endTime - System.currentTimeMillis(); } return (value == state); } }