import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* {@link <a href=
* "https://[Log in to view URL]"
* target= "_blank">sincronizzazione estesa di un thread pool</a>}
*
* @author itammb ( Italia Massimiliano Buscati )
* @version JDK 1.15
*
*/
class Main {
private static class BoundedBuffer<E> {
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private Object[] items;
private int putptr, takeptr, storage;
public BoundedBuffer(int storage) {
items = new Object[storage];
this.storage = putptr = takeptr = 0;
}
/**
* @see Condition#signal()
*
* {@link Lock#lock()} {@link Lock#unlock()}
*
*/
public void put(E x) throws InterruptedException {
lock.lock();
try {
isFull(); // buffer pieno, attesa
items[putptr] = x; // inserisce un elemento
nextPutIndex(); // avanza di una posizione il prossimo inserimento, diminuisce lo spazio di
// storage
notEmpty.signal();
} finally {
lock.unlock();
}
}
/**
* @see Condition#await()
*
*/
private void isFull() throws InterruptedException {
while (storage == items.length)
notFull.await();
}
private void nextPutIndex() {
if (++putptr == items.length)
putptr = 0;
++storage;
}
public E take() throws InterruptedException {
lock.lock();
try {
isEmpty(); // buffer vuoto, attesa
E x = (E) items[takeptr]; // estrae un elemento
nextTakeIndex(); // avanza di una posizione la prossima estrazione, aumenta lo spazio di storage
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
private void isEmpty() throws InterruptedException {
while (storage == 0)
notEmpty.await();
}
private void nextTakeIndex() {
if (++takeptr == items.length)
takeptr = 0;
--storage;
}
}
private static class UniTest<E> {
private static final int N_THREAD = 10;
private static final int STORAGE_BUFFER = 2000;
private static final long SHUTDOWN_MILLI_SECOND = 20000;
private final Random random = new Random();
private final SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss");
public void simulateCondition(BoundedBuffer<String> boundedBuff, int nThread) throws InterruptedException {
Thread[] challenge = new Thread[nThread];
for (int i = 0; i < nThread; ++i) {
Thread player = new Thread(() -> {
try {
if (random.nextInt() % 2 == 0)
log("Take", Thread.currentThread().getName(), boundedBuff.take());
else {
boundedBuff.put(Thread.currentThread().getName());
log("Put", Thread.currentThread().getName(), Thread.currentThread().getName());
}
} catch (InterruptedException ie) {
System.out.println(Thread.currentThread().getName() + " was Interrupted !!");
}
});
challenge[i] = player;
}
run(challenge);
}
private void run(Thread[] challenge) throws InterruptedException {
start(challenge);
Thread.sleep(SHUTDOWN_MILLI_SECOND);
shutdown(challenge);
}
private void start(Thread[] challenge) {
for (int i = 0; i < challenge.length; ++i)
challenge[i].start();
}
private void shutdown(Thread[] challenge) {
for (int i = 0; i < challenge.length; ++i)
if (challenge[i].isAlive())
challenge[i].interrupt();
}
private void log(String operation, String player, String element) {
System.out.println(operation + " >> " + ft.format(new Date()) + " >> " + player + " >> " + element);
}
}
public static void main(String args[]) throws InterruptedException {
// Unit test - accesso condizionato a una coda di thread
new UniTest<String>().simulateCondition(new BoundedBuffer<String>(UniTest.STORAGE_BUFFER), UniTest.N_THREAD);
}
}
To embed this project on your website, copy the following code and paste it into your website's HTML: