前言
线程池在我们开发中经常使用到,因此我们都要学习线程池的数据模型和计算模型。本章内容为个人结合学习案例和项目中使用的经验心得模拟使用一个自定义的线程池便于理解和总结
一、模型设计参考
通过源码学习可以把确认线程池中的4大主要组件为:拒绝策略、阻塞队列、线程池实现、线程工厂(本次为未实现)。
二、RejectPolicy代码实现
package com.imk.cases.juc.threadpool.dev;
/**
* 自定义拒绝策略
*
* @author darrn.xiang
* @date 2022/6/24 20:22
*/
@FunctionalInterface
public interface RejectPolicy<T> {
void reject(BlockingDeque<T> queue,T task);
}
三、BlockingDeque代码实现
package com.imk.cases.juc.threadpool.dev;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* 自定义阻塞队列
*
* @author darrn.xiang
* @date 2022/6/24 20:25
*/
public class BlockingDeque<T> {
private Deque<T> queue = new ArrayDeque<>();
private ReentrantLock lock = new ReentrantLock();
/**
* 生产者等待变量
*/
private Condition fullWaitSet = lock.newCondition();
/**
* 消费者等待变量
*/
private Condition emptyWaitSet = lock.newCondition();
/**
* 队列的容量
*/
private int capacity;
public BlockingDeque(int capacity){
this.capacity = capacity;
}
/**
* 带超时阻塞获取任务
*
* @param timeout
* @param unit
* @return
*/
public T poll(long timeout, TimeUnit unit){
lock.lock();
try{
long nanos = unit.toNanos(timeout);
while (queue.isEmpty()){
try {
if(nanos <= 0){
return null;
}
nanos = emptyWaitSet.awaitNanos(nanos);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
T t = queue.removeFirst();
fullWaitSet.signal();
return t;
}finally {
lock.unlock();
}
}
/**
* 阻塞获取任务
*
* @return
*/
public T take(){
lock.lock();
try{
while (queue.isEmpty()){
try {
emptyWaitSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
T t = queue.removeFirst();
fullWaitSet.signal();
return t;
}finally {
lock.unlock();
}
}
/**
* 阻塞添加任务
*
* @param task
*/
public void put(T task){
lock.lock();
try {
while (queue.size() == capacity){
try {
fullWaitSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.addLast(task);
emptyWaitSet.signal();
}finally {
lock.unlock();
}
}
/**
* 带超时时间阻塞添加任务
*
* @param task
* @param timeout
* @param timeUnit
* @return
*/
public boolean offer(T task,long timeout,TimeUnit timeUnit){
lock.lock();
try {
long nanos = timeUnit.toNanos(timeout);
while (queue.size() == capacity){
try {
if(nanos <= 0){
return false;
}
nanos = fullWaitSet.awaitNanos(nanos);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.addLast(task);
emptyWaitSet.signal();
return true;
}finally {
lock.unlock();
}
}
/**
* 返回队列的大小
*
* @return
*/
public int size(){
lock.lock();
try {
return queue.size();
}finally {
lock.unlock();
}
}
/**
* 尝试添加任务到队列
*
* @param task
* @param rejectPolicy
*/
public void tryPut(T task,RejectPolicy<T> rejectPolicy){
lock.lock();
try {
if(queue.size() == capacity){
rejectPolicy.reject(this,task);
}else {
queue.addLast(task);
emptyWaitSet.signal();
}
}finally {
lock.unlock();
}
}
}
四、ThreadPool代码实现
package com.imk.cases.juc.threadpool.dev;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
/**
* 自定义线程池
*
* @author darrn.xiang
* @date 2022/6/25 18:35
*/
public class ThreadPool {
private BlockingDeque<Runnable> taskQueue;
private HashSet<Worker> workers = new HashSet<>();
private int coreSize;
private long timeout;
private TimeUnit timeUnit;
private RejectPolicy<Runnable> rejectPolicy;
public ThreadPool(int coreSize, long timeout, TimeUnit timeUnit, int capacity, RejectPolicy<Runnable> rejectPolicy){
this.coreSize = coreSize;
this.timeout = timeout;
this.timeUnit = timeUnit;
this.taskQueue = new BlockingDeque<>(capacity);
this.rejectPolicy = rejectPolicy;
}
public void execute(Runnable task){
if(workers.size() < coreSize){
Worker worker = new Worker(task);
workers.add(worker);
worker.start();
}else{
taskQueue.tryPut(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.poll(timeout,timeUnit))!=null){
try {
task.run();
}catch (Exception exception){
exception.printStackTrace();
}finally {
task = null;
}
}
// 移除当前
synchronized (workers){
workers.remove(this);
}
}
}
}
五、测试验证
package com.imk.cases.juc.threadpool.dev;
import java.util.concurrent.TimeUnit;
/**
* 测试验证
*
* @author darrn.xiang
* @date 2022/6/25 18:59
*/
public class ThreadPoolTest {
public static void main(String[] args) {
ThreadPool threadPool = new ThreadPool(1, 1000, TimeUnit.MILLISECONDS, 1, new RejectPolicy<Runnable>() {
@Override
public void reject(BlockingDeque<Runnable> queue, Runnable task) {
// 1.死等
//queue.put(task);
// 2. 超时等待
//queue.offer(task,1500,TimeUnit.MILLISECONDS);
// 3.放弃任务
//System.out.println("放弃任务");
// 4.让调用者抛出异常
throw new RuntimeException("任务执行失败!"+task);
// 5) 让调用者自己执行任务
//task.run();
}
});
for (int i = 0; i < 4; i++) {
int j = i;
threadPool.execute(()->{
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(j);
});
}
}
}