Skip to content

Instantly share code, notes, and snippets.

@dramaticlly
Last active August 12, 2024 23:51
Show Gist options
  • Save dramaticlly/8ab4d6811c92c4fe00740be6234298ba to your computer and use it in GitHub Desktop.
Save dramaticlly/8ab4d6811c92c4fe00740be6234298ba to your computer and use it in GitHub Desktop.
Concurrent Primitive Test
...
Printer1 move from 62606 to 62607
Printer2 move from 62607 to 62608
Printer3 move from 62608 to 62609
Printer4 move from 62609 to 62610
Printer0 move from 62610 to 62611
Printer1 move from 62611 to 62612
Printer2 move from 62612 to 62613
Printer3 move from 62613 to 62614
Printer4 move from 62614 to 62615
Printer0 move from 62615 to 62616
Printer1 move from 62616 to 62617
Printer2 move from 62617 to 62618
Printer3 move from 62618 to 62619
Printer4 move from 62619 to 62620
Printer0 move from 62620 to 62621
Exception in thread "Printer2" Exception in thread "Printer3" java.lang.RuntimeException: java.lang.InterruptedException
at ConcurrentPrimitive.lambda$nPrinter$2(scratch.java:75)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.InterruptedException
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1609)
at ConcurrentPrimitive.lambda$nPrinter$2(scratch.java:68)
... 1 more
Exception in thread "Printer1" java.lang.RuntimeException: java.lang.InterruptedException
at ConcurrentPrimitive.lambda$nPrinter$2(scratch.java:75)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.InterruptedException
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1609)
at ConcurrentPrimitive.lambda$nPrinter$2(scratch.java:68)
... 1 more
java.lang.RuntimeException: java.lang.InterruptedException
at ConcurrentPrimitive.lambda$nPrinter$2(scratch.java:75)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.InterruptedException
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1609)
at ConcurrentPrimitive.lambda$nPrinter$2(scratch.java:68)
... 1 more
Exception in thread "Printer4" Exception in thread "Printer0" java.lang.RuntimeException: java.lang.InterruptedException
at ConcurrentPrimitive.lambda$nPrinter$2(scratch.java:75)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.InterruptedException
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1609)
at ConcurrentPrimitive.lambda$nPrinter$2(scratch.java:68)
... 1 more
java.lang.RuntimeException: java.lang.InterruptedException
at ConcurrentPrimitive.lambda$nPrinter$2(scratch.java:75)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.InterruptedException
at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1609)
at ConcurrentPrimitive.lambda$nPrinter$2(scratch.java:68)
... 1 more
Process finished with exit code 0
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import static java.util.concurrent.TimeUnit.SECONDS;
class ConcurrentPrimitive {
private static final ScheduledExecutorService SCHEDULER =
Executors.newScheduledThreadPool(2);
private final ReentrantLock lock = new ReentrantLock();
private AtomicInteger curr = new AtomicInteger();
private final Condition evenReady = lock.newCondition();
private final Condition oddReady = lock.newCondition();
private final Condition nReady = lock.newCondition();
private final Runnable EvenPrinter = () -> {
for (; ; ) {
lock.lock();
try {
while (curr.get() % 2 != 0) {
evenReady.await();
}
int before = curr.get();
int after = curr.incrementAndGet();
System.out.printf("%s move from %d to %d\n", Thread.currentThread().getName(), before, after);
oddReady.signalAll();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
};
private final Runnable OddPrinter = () ->
{
for (; ; ) {
lock.lock();
try {
while (curr.get() % 2 != 1) {
oddReady.await();
}
int before = curr.get();
int after = curr.incrementAndGet();
System.out.printf("%s move from %d to %d\n", Thread.currentThread().getName(), before, after);
evenReady.signalAll();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
};
private Runnable nPrinter(int size, int pos) {
return () ->
{
for (; ; ) {
lock.lock();
try {
while (curr.get() % size != pos) {
nReady.await();
}
int before = curr.get();
int after = curr.incrementAndGet();
System.out.printf("%s move from %d to %d\n", Thread.currentThread().getName(), before, after);
nReady.signalAll();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
};
}
public void beepForOneMinute() {
final Runnable beeper = () -> System.out.println("beep");
final ScheduledFuture<?> beeperHandle =
SCHEDULER.scheduleAtFixedRate(beeper, 1, 10, SECONDS);
SCHEDULER.schedule(() -> {
beeperHandle.cancel(true);
System.out.println("Done with beep");
}, 60, SECONDS);
}
public static void main(String[] args) throws InterruptedException {
ConcurrentPrimitive primitive = new ConcurrentPrimitive();
// scratch.beepForOneMinute();
// 2 printer coordination
// evenOddPrinterCoordination(scratch);
// n printer coordination
List<Thread> result = generalizedNPrinterCoordination(primitive, 5);
// cleanup
SCHEDULER.schedule(() -> {
result.forEach(Thread::interrupt);
}, 1, SECONDS);
SCHEDULER.shutdown();
SCHEDULER.awaitTermination(2, SECONDS);
}
/*
Use both instance of even and odd printer and 2 condition variable to coordinate the print
*/
public static void evenOddPrinterCoordination(ConcurrentPrimitive primitive) {
Thread threadEven = new Thread(primitive.EvenPrinter);
threadEven.setName("Even");
Thread threadOdd = new Thread(primitive.OddPrinter);
threadOdd.setName("Odd");
threadOdd.start();
threadEven.start();
}
public static List<Thread> generalizedNPrinterCoordination(ConcurrentPrimitive primitive, int n) {
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < n; i++) {
Thread curr = new Thread(primitive.nPrinter(n, i));
curr.setName("Printer" + i);
threads.add(curr);
}
// start
threads.forEach(Thread::start);
return threads;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment