import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
class processor {
// list to store number; + upper and lower limit for number of elements
private List list = new ArrayList<>();
private final int MAX_Limit = 10;
private final int MIN_Limit = 0;
// lock with corresponding conditions
private final ReentrantLock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
// value that is added to the list
private int value = 0 ;
// method to fill the list
public void producer() throws InterruptedException {
while(true) { // work forever
lock.lock(); // try to aquire lock
try {
while (list.size() >= MAX_Limit){ // If the maximal size of the list is reached,
System.out.println("Waiting for consumer to consume the numbers ....");
notFull.await(); // then wait
}
System.out.println("Adding the number " + value + " to list with " + list.size() + " elements.");
list.add(value); // add number to list
value++;
notEmpty.signal(); // Signal that the list is not empty
} finally {
lock.unlock(); // unlock after finishing work
}
Thread.sleep((long) (Math.random() * 500)); // sleep random time
}
}
// method to delete elements from the list
public void consumer() throws InterruptedException {
while(true) { // work forever
lock.lock(); // try to aquire lock
try {
while (list.size() <= MIN_Limit){ // If the minimal size of the list is reached,
System.out.println("Waiting for producer to produce the numbers ....");
notEmpty.await(); // then wait
}
int n = list.remove(list.size()-1); // remove element from list
System.out.println("Removing the number " + n +
" from list with " + (int) (list.size()+1) + " elements.");
notFull.signal(); // Signal that the list is not full
} finally {
lock.unlock(); // unlock after finishing work
}
Thread.sleep((long) (Math.random() * 500));
}
}
}
public class PCLocks {
public static void main(String[] args) {
processor process = new processor();
// create producer thread
Thread T1 = new Thread(new Runnable() {
@Override
public void run() {
try{
process.producer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// produce consumer thread
Thread T2 = new Thread(new Runnable() {
@Override
public void run() {
try{
process.consumer();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
// start both threads
T1.start();
T2.start();
// wait for threads to finish (will not happen...)
try {
T1.join();
T2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}