自定义线程池代码实现--2

原理

在这里插入图片描述

代码实现

测试类

//自定义线程池
public class TestPool {
public static void main(String[] args) {
    //test
    ThreadPool threadPool = new ThreadPool(3, 5, TimeUnit.MICROSECONDS, 6);
    for (int i = 0; i < 10; i++) {
        int j = i;
        threadPool.execute(()->{
            System.out.println(Thread.currentThread().getName()+"==>执行任务"+j);
        });
    }
}
}

线程池

class ThreadPool{
//任务队列
private BlookingQueue<Runnable> queue;
//线程集合
private HashSet<Work> works = new HashSet<Work>();
//核心线程数
private int corePoolSize;
//超时任务的超时时间
private long times;
//工具类
private TimeUnit unit;


//构造方法
public ThreadPool(int corePoolSize, long times, TimeUnit unit,int queueSize) {
    this.corePoolSize = corePoolSize;
    this.times = times;
    this.unit = unit;
    queue = new BlookingQueue<>(queueSize);
}
//执行任务
public void execute(Runnable runnable){
    synchronized (works){
        //当任务没有超过核心线程数时,直接交给work执行
        //当任务超过核心线程数时,放入任务队列
        if (works.size()<corePoolSize){
            Work work = new Work(runnable);
            System.out.println(work.getName()+"===>被创建");
            works.add(work);
            work.start();
        }else {
            queue.setTask(runnable);
        }
    }

}

线程包装类

class Work extends Thread{
    private Runnable task;

    public Work(Runnable task) {
        this.task = task;
    }

    @Override
    public void run() {
        //执行任务 当task不为空 和 任务队列有值
        while (task!=null || (task = queue.poll(times,unit))!=null){//pool()方法保证了线程安全 并且不会让线程一直等待
           try{
               task.run();
           }catch (Exception e){
               e.printStackTrace();
           }finally {
               task=null;
           }
        }
        //当没有任务时 将线程从线程池中移除
        synchronized (works){
            System.out.println(Thread.currentThread().getName()+"===>被移除");
            works.remove(this);
        }
    }
}
}

任务队列

class BlookingQueue<T>{
	//阻塞队列
private Deque<T> queue = new ArrayDeque<>();

   //阻塞队列的容量
private int capacity;

//锁
private ReentrantLock lock = new ReentrantLock();

//队列满的条件变量
private Condition fullWaitSet = lock.newCondition();

//队列空的条件变量
private Condition emptyWaitSet = lock.newCondition();

public BlookingQueue(int capacity) {
    this.capacity = capacity;
}

//获取任务 带超时
public T poll(long timemills, TimeUnit unit){
    //将等待时间返回为纳秒
    long nanos = unit.toNanos(timemills);
    lock.lock();
    try{
        //队列为空 让线程阻塞
        while (queue.isEmpty()){
            try {
                //如果等待时间小于0,说明已经超时
                if (nanos<=0){
                    return null;
                }
                //返回值为上次等待后的剩余时间
                 nanos = emptyWaitSet.awaitNanos(nanos);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        T t = queue.removeFirst();
        //唤醒等待添加任务的线程
        fullWaitSet.signalAll();
        return t;
    } finally {
        lock.unlock();
    }
}


//获取任务
public T getTask(){
    lock.lock();
    try{
        //队列为空 让线程阻塞
        while (queue.isEmpty()){
            try {
                emptyWaitSet.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        T t = queue.removeFirst();
        //唤醒等待添加任务的线程
        fullWaitSet.signalAll();
        return t;
    } finally {
        lock.unlock();
    }
}

//添加任务
public void setTask(T t){
    lock.lock();
    try{
        //队列满的话 让线程阻塞
        while(queue.size()==capacity){
            try {
                fullWaitSet.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        queue.addLast(t);
        //换醒等待获取任务的线程
        emptyWaitSet.signalAll();
    }finally {
        lock.unlock();
    }
}

//获取队列的大小
public int getSize(){
    lock.lock();
    try{
        return queue.size();
    }finally {
        lock.unlock();
    }
}
}

测试结果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_44017425/article/details/107608004
今日推荐