import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
class Main {
public static void main(String[] args) {
ConcurrentRunner runner = new ConcurrentRunner();
CompletableFuture<Void> future1 = runner.startVolatile();
CompletableFuture<Void> future2 = runner.startVolatile();
CompletableFuture.allOf(future1, future2).join();
System.out.println("Done with volatile");
CompletableFuture<Void> future3 = runner.startLock();
CompletableFuture<Void> future4 = runner.startLock();
CompletableFuture.allOf(future3, future4).join();
System.out.println("Done with lock");
System.exit(0);
}
}
class ConcurrentRunner {
private volatile int i = 0;
private Executor executor = Executors.newCachedThreadPool();
private final Object lock = new Object();
private int count = 0;
CompletableFuture<Void> startVolatile() {
return CompletableFuture.runAsync(() -> {
while (i < 100) {
System.out.println(i++);
}
}, executor);
}
CompletableFuture<Void> startLock() {
return CompletableFuture.runAsync(() -> {
synchronized (lock) {
while (count < 100) {
System.out.println(count++);
}
}
}, executor);
}
}