@Slf4j(topic = "c.Test")
public class Test {
static AtomicStampedReference<String> s = new AtomicStampedReference<>("A", 0);
@SneakyThrows
public static void main(String[] args) {
ThreadPool threadPool = new ThreadPool(1, 1, TimeUnit.SECONDS, 3, (queue, task) -> {
log.debug("already full.");
throw new RuntimeException();
});
for (int i = 0; i < 5; i++) {
int j = i;
threadPool.execute(() -> {
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.debug("execute log -> {}", j);
});
}
}
}
@Slf4j(topic = "c.ThreadPool")
class ThreadPool {
private BlockingQueue<Runnable> taskQueue;
private int coreSize;
private HashSet<Worker> workers = new HashSet<Worker>();
private long timeout;
private TimeUnit timeUnit;
private RejectPolicy<Runnable> rejectPolicy;
public ThreadPool(int coreSize, long timeout, TimeUnit timeUnit, int queueSize,
RejectPolicy<Runnable> rejectPolicy) {
this.coreSize = coreSize;
this.timeout = timeout;
this.timeUnit = timeUnit;
this.taskQueue = new BlockingQueue<>(queueSize);
this.rejectPolicy = rejectPolicy;
}
public void execute(Runnable task) {
synchronized (workers) {
if (workers.size() < coreSize) {
log.debug("new worker: {}", task);
Worker worker = new Worker(task);
workers.add(worker);
worker.start();
} else {
log.debug("add taskQueue: {}", task);
taskQueue.add(task, rejectPolicy);
}
}
}
class Worker extends Thread{
private Runnable task;
public Worker(Runnable task) {
this.task = task;
}
@Override
public void run() {
while (task != null || (task = taskQueue.take(1, timeUnit)) != null) {
try {
log.debug("run task: {}", task);
task.run();
} finally {
task = null;
}
}
synchronized (workers) {
log.debug("remove worker: {}", this);
workers.remove(this);
}
}
}
}
@Slf4j(topic = "c.BlockingQueue")
class BlockingQueue<T> {
private Deque<T> deque;
private ReentrantLock lock = new ReentrantLock();
private Condition fullWaitSet = lock.newCondition();
private Condition emptyWaitSet = lock.newCondition();
private int size;
public BlockingQueue(int size) {
this.size = size;
deque = new ArrayDeque<>();
}
public T take() {
try {
lock.lock();
while (deque.isEmpty()) {
emptyWaitSet.await();
}
T t = deque.removeFirst();
fullWaitSet.signal();
return t;
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
public T take(long timeout, TimeUnit unit) {
try {
lock.lock();
long nanos = unit.toNanos(timeout);
while (deque.isEmpty()) {
if (nanos <= 0) {
return null;
}
nanos = emptyWaitSet.awaitNanos(nanos);
}
T t = deque.removeFirst();
fullWaitSet.signal();
return t;
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
public boolean add(T t) {
try {
lock.lock();
while (deque.size() == size) {
fullWaitSet.await();
}
deque.addLast(t);
emptyWaitSet.signal();
return true;
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
public boolean add(T t, long timeout, TimeUnit unit) {
try {
lock.lock();
long nanos = unit.toNanos(timeout);
while (deque.size() == size) {
if (nanos <= 0) {
return false;
}
nanos = fullWaitSet.awaitNanos(nanos);
}
deque.addLast(t);
emptyWaitSet.signal();
return true;
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
public boolean add(T t, RejectPolicy<T> rejectPolicy) {
try {
lock.lock();
if (deque.size() == size) {
log.debug("full.");
rejectPolicy.reject(this, t);
} else {
deque.addLast(t);
emptyWaitSet.signal();
}
return true;
} finally {
lock.unlock();
}
}
}
@FunctionalInterface
interface RejectPolicy<T> {
void reject(BlockingQueue<T> queue, T task);
}