package org.httpkit.server;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadPool3 {
private final Worker[] workers;
private volatile boolean closed = false;
private final CountDownLatch latch;
// private final int size;
private BlockingQueue queue;
class BlockingQueue {
final Runnable[] items;
/** items index for next take, poll, peek or remove */
int takeIndex;
/** items index for next put, offer, or add */
int putIndex;
/** Number of elements in the queue */
int count;
/** Main lock guarding all access */
final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
public BlockingQueue(int capacity) {
this.items = new Runnable[capacity];
lock = new ReentrantLock();
notEmpty = lock.newCondition();
}
public boolean offer(Runnable r) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count == items.length) {
return false;
} else {
items[putIndex] = r;
putIndex = (++putIndex == items.length) ? 0 : putIndex;
++count;
if (count == 1) {
// System.out.println("signal");
notEmpty.signal();
}
return true;
}
} finally {
lock.unlock();
}
}
public Runnable take() {
final ReentrantLock lock = this.lock;
for (;;) {
lock.lock();
try {
if (count > 0) {
final Runnable[] items = this.items;
Runnable r = items[takeIndex];
items[takeIndex] = null;
takeIndex = (++takeIndex == items.length) ? 0 : takeIndex;
--count;
return r;
} else if (closed) {
return null;
} else {
// System.out.println("wait");
notEmpty.await();
}
} catch (InterruptedException ignore) {
} finally {
lock.unlock();
}
}
}
}
class Worker implements Runnable {
final BlockingQueue queue;
final Thread t;
public Worker(BlockingQueue queue) {
this.queue = queue;
t = new Thread(this);
}
public void run() {
Runnable r;
while ((r = queue.take()) != null) {
r.run();
}
latch.countDown();
}
}
public ThreadPool3(int size, int total) {
// this.size = size;
this.workers = new Worker[size];
this.queue = new BlockingQueue(total);
this.latch = new CountDownLatch(size);
for (int i = 0; i < size; i++) {
workers[i] = new Worker(queue);
workers[i].t.start();
}
}
// private volatile int c = 0;
public void submit(Runnable task) {
queue.offer(task);
// if (!workers[task.hashCode() % size].queue.offer(task)) {
// // System.out.println("oveload");
// }
}
// public void submit()
public void coseAndwait() throws InterruptedException {
closed = true;
for (Worker w : workers) {
w.t.interrupt();
}
latch.await();
}
}