手写线程池

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();
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fairy要carry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值