// lowlevel/SynchronizedComparison.java // (c)2017 MindView LLC: see Copyright.txt // We make no guarantees that this code is fit for any purpose. // Visit http://OnJava8.com for more book information. // Synchronizing blocks instead of entire methods // speeds up access. import java.util.*; import java.util.stream.*; import java.util.concurrent.*; import java.util.concurrent.atomic.*; import onjava.Nap; abstract class Guarded { AtomicLong callCount = new AtomicLong(); public abstract void method(); @Override public String toString() { return getClass().getSimpleName() + ": " + callCount.get(); } } class SynchronizedMethod extends Guarded { public synchronized void method() { new Nap(10); callCount.incrementAndGet(); } } class CriticalSection extends Guarded { public void method() { new Nap(10); synchronized(this) { callCount.incrementAndGet(); } } } class Caller implements Runnable { private Guarded g; public Caller(Guarded g) { this.g = g; } private AtomicBoolean stop = new AtomicBoolean(false); class Stop extends TimerTask { @Override public void run() { stop.set(true); } } @Override public void run() { new Timer().schedule(new Stop(), 2500); while(!stop.get()) g.method(); } } public class SynchronizedComparison { static void test(Guarded g) { List> callers = Stream.of( new Caller(g), new Caller(g), new Caller(g), new Caller(g)) .map(CompletableFuture::runAsync) .collect(Collectors.toList()); callers.forEach(CompletableFuture::join); System.out.println(g); } public static void main(String[] args) { test(new CriticalSection()); test(new SynchronizedMethod()); } } /* Output: CriticalSection: 972 SynchronizedMethod: 247 */