package com.example.juc.ThreadPool;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author diao 2022/4/19
*/
@Slf4j(topic = "c.PoolTest")
public class PoolTest {
public static void main(String[] args) throws InterruptedException {
/**实例化线程池
* queueCapcity:任务队列容量
* coreSize:核心线程数
*/
log.debug("开始...");
ThreadPool threadPool = new ThreadPool(1, 1, 1000, TimeUnit.MILLISECONDS,((queue, task) -> {
/*1.死等*/
// queue.put(task);
/*2.带超时等待*/
queue.offer(task,1500,TimeUnit.MILLISECONDS);
/*3.让调用者自己执行任务*/
// task.run();
}));
/*执行任务,i个任务*/
for (int i = 0; i < 3; i++) {
int j=i;
threadPool.execute(()->{
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("{}",j);
});
}
}
}
@FunctionalInterface//拒绝策略,可以使用lambda
interface RejectPolicy<T>{
/**
* 拒绝策略的方法,具体实现由调用者触发
* @param queue:任务队列
* @param task:任务
*/
void reject(BlockingQueue queue,Runnable task) throws InterruptedException;
}
/**
* 自定义线程池
*/
@Slf4j(topic = "c.ThreadPool")
class ThreadPool {
//1.任务队列
private BlockingQueue<Runnable> taskQueue;
//2.线程集合
private HashSet<Worker> workers = new HashSet<Worker>();
//3.核心线程数
private int coreSize;
//4.获取任务的超时时间
private long timeout;
private TimeUnit timeUnit;
//5.拒绝策略,里面封装的是任务
private RejectPolicy<Runnable> rejectPolicy;
/**
* 定义线程池
* @param queueCapcity:任务队列容量
* @param coreSize:核心线程数
* @param timeout:超时时间
* @param timeUnit:用来转化时间
*/
public ThreadPool(int queueCapcity, int coreSize, long timeout, TimeUnit timeUnit,RejectPolicy rejectPolicy) {
this.taskQueue=new BlockingQueue<>(queueCapcity);
this.coreSize = coreSize;
this.timeout = timeout;
this.timeUnit = timeUnit;
this.rejectPolicy=rejectPolicy;
}
/**线程池中的执行任务方法
*执行任务:保证永远只有coreSize个线程循环执行任务
*/
public void execute(Runnable task) throws InterruptedException {
/**
* 任务数与线程数coreSize的关系
*/
synchronized (workers){
//如果线程集合小于线程初始化的核心数,就添加新的线程
if(workers.size()<coreSize){
Worker worker = new Worker(task);
log.debug("新增worker{},{}",worker,task);
workers.add(worker);
worker.start();
}else{
//如果线程集合数>=设定的线程数,加入任务队列缓存,因为线程数已经很大了,要执行任务
// log.debug("加入任务队列{}",task);
/*taskQueue.put(task);*/
taskQueue.tryPut(rejectPolicy,task);
}
}
}
//用来封装线程,Runnable形式
class Worker extends Thread{
private Runnable task;
public Worker(Runnable task) {
this.task = task;
}
@Override
public void run() {
/**
* 执行任务,线程中的任务不为空或者任务队列中没有任务,不断进行探索
* while(task!=null||(task=taskQueue.take())!=null){
* 以下是超时的判断,如果超时,poll会返回null
*/
while(task!=null||(task=taskQueue.poll(timeout,timeUnit))!=null){
try {
log.debug("开始运行...{}",task);
task.run();
} catch (Exception e) {
e.printStackTrace();
} finally {
/*执行完任务后,任务记得要为null*/
log.debug("任务执行完毕",task);
task=null;
}
}
/*所有任务执行完后,线程需要等待*/
synchronized (workers){
log.debug("worker被移除{}",this);
workers.remove(this);
}
}
}
}
@Slf4j(topic = "c.BlockingQueue")
class BlockingQueue<T>{
//1.任务队列
private Deque<T> queue=new ArrayDeque<>();
//2.锁
private ReentrantLock lock=new ReentrantLock();
//3.生产者条件变量(通过锁newCondition创建的休息室)
private Condition fullWaitSet=lock.newCondition();
//4.消费者条件变量
private Condition emptyWaitSet=lock.newCondition();
//5.容量
private int capcity;
public BlockingQueue(int capcity) {
this.capcity = capcity;
}
/**
* 带超时的阻塞获取
* @param timeout:时间
* @param unit:时间规定
* @return:获取任务
*/
public T poll(long timeout,TimeUnit unit){
lock.lock();
try {
/*1、同一将timeout转化为纳秒*/
long nanos = unit.toNanos(timeout);
/*2、如果任务队列为null线程等待一下,如果超时,返回null*/
while (queue.isEmpty()) {
try {
if (nanos <= 0) {
/*没有等到,直接返回*/
return null;
}
nanos = emptyWaitSet.awaitNanos(nanos);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*3.获取头元素,就是任务队列中的元素
* 然后唤醒线程休息室*/
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();
}
}
/**
* 阻塞添加,在任务队列中添加新任务
*/
public void put(T element){
lock.lock();
try{
/*1.如果任务队列元素已经满了*/
while(queue.size()==capcity){
try {
log.debug("等待加入任务队列{}...",element);
/*2.进入任务的休息室等待*/
fullWaitSet.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("加入任务队列{}",element);
/*3.如果队列未满,元素放到尾部,此时队列有元素,唤醒消费线程*/
queue.addLast(element);
emptyWaitSet.signal();
}finally {
lock.unlock();
}
}
/**
* 超时时间的添加任务方法
* @param task
* @param timeout
* @param timeUnit
* @return
* @throws InterruptedException
*/
public boolean offer(T task,long timeout,TimeUnit timeUnit) throws InterruptedException {
lock.lock();
try{
/*1.将超时时间转化一下纳秒*/
long nanos=timeUnit.toNanos(timeout);
while(queue.size()==capcity) {
log.debug("开始等待加入任务队列{}...", task);
/*2.如果超时*/
if (nanos <= 0) {
return false;
}
nanos = fullWaitSet.awaitNanos(nanos);
}
/*3.如果线程不满的话,就加入队列,最后唤醒线程消费任务*/
log.debug("加入任务队列{}",task);
queue.addLast(task);
emptyWaitSet.signal();
return true;
}finally {
lock.unlock();
}
}
//获取大小
public int size(){
lock.lock();
try{
return queue.size();
}finally {
lock.unlock();
}
}
//按照策略添加任务
public void tryPut(RejectPolicy<T> rejectPolicy, T task) throws InterruptedException {
lock.lock();
try{
/*1.判断任务队列是否满了*/
if(queue.size()==capcity){
rejectPolicy.reject(this, (Runnable) task);
}else{
/*2.有空闲空间*/
log.debug("加入任务队列{}",task);
queue.addLast(task);
/*3.唤醒线程起来消费*/
emptyWaitSet.signal();
}
}finally {
lock.unlock();
}
}
}