class ThreadPool {
private BlockQueue<Runnable> taskQueue;
private int coreSize;
private List<Worker> workers = new Vector<>();
private long takeTime;
private TimeUnit takeTimeUnit;
public ThreadPool (int coreSize, int taskQueueCapacity,long takeTime, TimeUnit takeTimeUnit) {
this.taskQueue = new BlockQueue<>(taskQueueCapacity);
this.coreSize = coreSize;
this.takeTime = takeTime;
this.takeTimeUnit = takeTimeUnit;
}
public void execute(Runnable task) {
synchronized (workers) {
if (workers.size() < coreSize) {
Worker worker = new Worker(task);
workers.add(worker);
worker.start();
} else {
taskQueue.tryPut(task, (blockQueue, t) -> {
task.run();
});
}
}
}
class Worker extends Thread {
Runnable task;
public Worker(Runnable task) {
this.task = task;
}
@Override
public void run() {
while (task != null || (task = taskQueue.take(takeTime, takeTimeUnit)) != null) {
try {
task.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
task = null;
}
}
synchronized (workers) {
workers.remove(this);
}
}
}
}
class BlockQueue<T> {
private Deque<T> queue = new ArrayDeque<T>();
private ReentrantLock lock = new ReentrantLock();
private Condition fullWaitSet = lock.newCondition();
private Condition emptyWaitSet = lock.newCondition();
private int capacity;
public BlockQueue(int capacity) {
this.capacity = capacity;
}
public T take() {
lock.lock();
try {
while (queue.isEmpty()) {
try {
emptyWaitSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
fullWaitSet.signal();
return queue.removeFirst();
} finally {
lock.unlock();
}
}
public T take(long time, TimeUnit timeUnit) {
long nanos = timeUnit.toNanos(time);
lock.lock();
try {
while (queue.isEmpty()) {
try {
if (nanos <= 0) {
return null;
}
nanos = emptyWaitSet.awaitNanos(nanos);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
fullWaitSet.signal();
return queue.removeFirst();
} finally {
lock.unlock();
}
}
public void tryPut(T t, BiConsumer<BlockQueue<T>, T> consumer) {
lock.lock();
try {
if (queue.size() < capacity) {
queue.addLast(t);
emptyWaitSet.signal();
} else {
consumer.accept(this, t);
}
} finally {
lock.unlock();
}
}
public void put(T t) {
System.out.println(queue.size());
lock.lock();
try {
while (queue.size() == capacity) {
try {
fullWaitSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.addLast(t);
} finally {
lock.unlock();
}
}
}