package javaBasic;import java.util.concurrent.atomic.AtomicBoolean;import java.util.concurrent.atomic.AtomicInteger;public class JavaAmoticTest { static abstract class CalculatorBase { // Creates a new {@code AtomicBoolean} with initial value {@code false}. AtomicBoolean calledStart = new AtomicBoolean(); AtomicBoolean calledDispose = new AtomicBoolean(); protected void StartCore() { boolean called = calledStart.getAndSet(true); // if Called is False, Keeping Running // if not match, throw java.lang.AssertionError // and output error message. assert !called; try { Thread.sleep(1000); System.out.println("Start Finished"); } catch (InterruptedException e) { } } protected void DisposeCore() { boolean called = calledDispose.getAndSet(true); assert !called; try { Thread.sleep(1000); System.out.println("Dispose Finished"); } catch (InterruptedException e) { } } public abstract void Start(); public abstract void Dispose(); } static class CasCalculator extends CalculatorBase { // Creates a new AtomicInteger with the given initial value. AtomicInteger state = new AtomicInteger(kNotStarted); static final int kNotStarted = 0, kStarting = 1, kStarted = 2, kDisposed = 3; @Override public void Start() { // Atomically sets the value to the given updated value // if the current value {@code ==} the expected value. boolean succeed = state.compareAndSet(kNotStarted, kStarting); if (succeed) { synchronized (this) { StartCore(); } boolean cont = state.compareAndSet(kStarting, kStarted); if (!cont) { synchronized (this) { DisposeCore(); } } } } @Override public void Dispose() { // Atomically sets to the given value and returns the old value. int orig = state.getAndSet(kDisposed); if (orig == kStarted) { synchronized (this) { DisposeCore(); } } } public static void main(String[] args) throws InterruptedException { final CasCalculator cal = new CasCalculator(); new Thread() { @Override public void run() { cal.Start(); } }.start(); new Thread() { @Override public void run() { cal.Start(); } }.start(); new Thread() { @Override public void run() { cal.Start(); } }.start(); } }}