java线程(1) —— 自定义线程池(2)
上篇文章存在的问题
- put方法没有超时等待,如果消息队列没有消费,
- 如果消息队列一直是满的,生产者应该是什么操作,有以下的几种策略
- 超时等待
- 让调用者放弃任务执行
- 死等
- 让调用者抛出异常
- 让调用者自己执行任务
上面所说的这些个策略,如果按照之前的if else 写 就很烦。将这个什么策略。让调用者来实现。在这里实现一个接口,将实现方式给调用者给。
1. 超时等待
public void push(T task, long awaitTime, TimeUnit unit) {
/*
流程
- 判断满不满
- 不满就放,满就等待
- 唤醒等待线程
*/
//上锁
lock.lock();
try {
//时间单位变为一样 nanos
long l = unit.toNanos(awaitTime);
while (capcity == deque.size()) {
try {
log.debug("队列已经满,fullwaitset:{}", fullWaitSet);
//超时等待
l = fullWaitSet.awaitNanos(l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
deque.addLast(task);
emptyWaitSet.signalAll();
} finally {
lock.unlock();
}
}
2. 策略模式(由调用者决定)
写一个函数式的接口
//函数式接口
@FunctionalInterface
interface RejectPolicy<T>{
/**
* 在创建线程池的时候将代码执行什么策略
* @param queue
* @param task
*/
void reject(BlockQueue<T> queue, T task);
}
** 在消息队列中写一个tryPut方法**
/**
* 尝试获取锁
* @param rejectPolicy 策略
* @param task 任务对象
*/
public void tryPut(RejectPolicy rejectPolicy,T task){
/*
流程
- 判断满不满
- 不满就放,满就等待
- 唤醒等待线程
*/
//上锁
lock.lock();
try {
//时间单位变为一样 nanos
while (capcity == deque.size()) {
log.debug("队列已经满, stackDeque:{}",task);
//这里执行调用者传过来的代码
rejectPolicy.reject(this,task);
}
deque.addLast(task);
emptyWaitSet.signalAll();
} finally {
lock.unlock();
}
}
修改线程池的execute方法
/**
* 线程池 执行任务的方法
*
* @param task 需要执行的任务
*/
public void execute(Runnable task) {
/**
* 创建线程执行任务.
* 懒惰初始化;
* - 如果workset的数量小于coresize 那就创建,执行任务
* - 否则:任务进任务队列
* 这里要加锁:因为work是公用的,
*/
synchronized (works) {
if (works.size() < coreSize) {
//创建
Work work = new Work(task);
// 添加线程进works集合
works.add(work);
//开启线程
work.start();
} else {
//任务进消息队列
taskQueue.tryPut(rejectPolicy,task); // 主要修改的是这里
}
}
}
测试
public static void main(String[] args) {
ThreadPool threadPool = new ThreadPool(1, 1, 1000L, TimeUnit.SECONDS,(blockQueue,task)->{
//死等
blockQueue.put(task);
});
for (int i = 0; i < 3; i++) {
int j = i;
threadPool.execute(()->{
try {
TimeUnit.SECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("{}",j);
});
}
}