Last active
August 12, 2024 23:51
-
-
Save dramaticlly/8ab4d6811c92c4fe00740be6234298ba to your computer and use it in GitHub Desktop.
Concurrent Primitive Test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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