diff --git a/src/exercises/ex_o/LockedWithConditionsStack.java b/src/exercises/ex_o/LockedWithConditionsStack.java new file mode 100644 index 0000000..e14d797 --- /dev/null +++ b/src/exercises/ex_o/LockedWithConditionsStack.java @@ -0,0 +1,51 @@ +package exercises.ex_o; + +import java.util.Stack; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +public class LockedWithConditionsStack { + private final int capacity; + private final Stack stack = new Stack<>(); + private final ReentrantLock lock = new ReentrantLock(); + private final Condition fullCondition = lock.newCondition(); + private final Condition emptyCondition = lock.newCondition(); + + public LockedWithConditionsStack(int capacity) { + this.capacity = capacity; + } + + public void pushToStack(int value) { + try { + lock.lock(); + while (stack.size() == capacity) { + System.out.println("Stack is full, waiting until someone pops"); + fullCondition.await(); + } + stack.push(value); + emptyCondition.signalAll(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + lock.unlock(); + } + } + + public int popFromStack() { + int value; + try { + lock.lock(); + while (stack.isEmpty()) { + System.out.println("Stack is empty, waiting until someone pushes"); + emptyCondition.await(); + } + value = stack.pop(); + fullCondition.signalAll(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + lock.unlock(); + } + return value; + } +} diff --git a/src/exercises/ex_o/NumberConsumer.java b/src/exercises/ex_o/NumberConsumer.java new file mode 100644 index 0000000..6643f01 --- /dev/null +++ b/src/exercises/ex_o/NumberConsumer.java @@ -0,0 +1,16 @@ +package exercises.ex_o; + +public class NumberConsumer implements Runnable { + private LockedWithConditionsStack stack; + + public NumberConsumer(LockedWithConditionsStack stack) { + this.stack = stack; + } + + @Override + public void run() { + while (true) { + System.out.println("Pop from stack: " + stack.popFromStack()); + } + } +} diff --git a/src/exercises/ex_o/NumberProducer.java b/src/exercises/ex_o/NumberProducer.java new file mode 100644 index 0000000..112cfa4 --- /dev/null +++ b/src/exercises/ex_o/NumberProducer.java @@ -0,0 +1,17 @@ +package exercises.ex_o; + +public class NumberProducer implements Runnable { + private LockedWithConditionsStack stack; + public NumberProducer(LockedWithConditionsStack stack) { + this.stack = stack; + } + + @Override + public void run() { + for (int i = 0; i < 100; i++) { + System.out.println("Pushing to stack " + i + "..."); + stack.pushToStack(i); + System.out.println("Pushed to stack " + i); + } + } +} diff --git a/src/exercises/ex_o/TestingReentrantLockWithConditions.java b/src/exercises/ex_o/TestingReentrantLockWithConditions.java new file mode 100644 index 0000000..62883bc --- /dev/null +++ b/src/exercises/ex_o/TestingReentrantLockWithConditions.java @@ -0,0 +1,9 @@ +package exercises.ex_o; + +public class TestingReentrantLockWithConditions { + public static void main(String[] args) { + LockedWithConditionsStack stack = new LockedWithConditionsStack(5); + (new Thread(new NumberProducer(stack))).start(); + (new Thread(new NumberConsumer(stack))).start(); + } +}