自定义线程池

本文介绍了自定义线程池的重要性,强调了线程池预先创建线程以提高响应速度和避免资源浪费。讨论了使用阻塞双端队列作为任务缓存,并详细阐述了当线程池和队列满载时的拒绝策略,包括阻塞等待、超时和异常处理等不同选项。

自定义线程池

前言

  • 线程池是由线程 + 队列形成的
  • 创建线程要花费昂贵的资源和时间,如果任务来了才创建线程那么响应时间会变长,而且一个进程能创建的线程数有限
  • 为了避免这些问题,在程序启动的时候就创建若干线程来响应处理,它们被称为线程池,里面的线程叫工作线程
  • 因此,我们可以根据以上要求,创建出自己的线程池
    在这里插入图片描述

阻塞双端队列

  • 利用阻塞队列来存放 暂时 无法处理的 任务
public class MyBlockingQueue<T> {

    private Deque<T> queue = new ArrayDeque<>();

    private ReentrantLock lock = new ReentrantLock();

    private Condition emptyWaitSet = lock.newCondition();

    private Condition fullWaitSet = lock.newCondition();

    private int capacity;

    private final int DEFAULT_CAPACITY = 16;

    public MyBlockingQueue() {
        capacity = DEFAULT_CAPACITY;
    }

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

    public T poll() {
        lock.lock();
        try {
            while (queue.isEmpty()) {
                emptyWaitSet.await();
            }
            T task = queue.removeFirst();
            fullWaitSet.signal();
            return task;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return null;
    }


    public T poll(long timeout, TimeUnit unit) {
        lock.lock();
        try {
            long nanos = unit.toNanos(timeout);
            while (queue.isEmpty()) {
                if (nanos <= 0) {
                    return null;
                }
                nanos = emptyWaitSet.awaitNanos(nanos);
            }
            T task = queue.removeFirst();
            fullWaitSet.signal();
            return task;
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return null;
    }

    public void put(T task) {
        lock.lock();
        try {
            while (queue.size() == capacity) {
                fullWaitSet.await();
            }
            queue.addLast(task);
            emptyWaitSet.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public boolean put(T task,long timeout,TimeUnit timeUnit) {
        lock.lock();
        try {
            long nanos = timeUnit.toNanos(timeout);
            while (queue.size() == capacity) {
                if (nanos <= 0) {
                    return false;
                }
                nanos = fullWaitSet.awaitNanos(nanos);
            }
            queue.addLast(task);
            emptyWaitSet.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return true;
    }

    public void put(MyRejectPolicy<T> rejectPolicy, T task) {
        lock.lock();
        try {
            if (queue.size() == capacity) {
                rejectPolicy.reject(this,task);
            }
            queue.addLast(task);
            emptyWaitSet.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public int size() {
        lock.lock();
        try {
            return queue.size();
        } finally {
            lock.unlock();
        }
    }

}

拒绝策略

  • 当线程池中的线程都处于忙碌状态,且阻塞队列已满时,我们根据需要可能会选择 阻塞等待,超时等待,抛出异常,放弃执行等方式,因此,可以利用策略模式,定义一个策略接口,由用户自己选择 需要 执行 的拒绝策略
@FunctionalInterface
interface MyRejectPolicy<T> {
    void reject(MyBlockingQueue<T> queue,T task);
}

线程池

public class MyThreadPool {
    private MyBlockingQueue<Runnable> taskQueue;

    private Set<Worker> workers = new HashSet<>();

    private int coreSize;

    private long timeout;

    private TimeUnit timeUnit;

    private MyRejectPolicy<Runnable> rejectPolicy;

    public MyThreadPool(int coreSize, long timeout, TimeUnit timeUnit,int queueCapacity,MyRejectPolicy<Runnable> rejectPolicy) {
        this.taskQueue = new MyBlockingQueue<>(queueCapacity);
        this.coreSize = coreSize;
        this.timeout = timeout;
        this.timeUnit = timeUnit;
        this.rejectPolicy = rejectPolicy;
    }

    public MyThreadPool(int coreSize, long timeout, TimeUnit timeUnit) {
        this.taskQueue = new MyBlockingQueue<>();
        this.coreSize = coreSize;
        this.timeout = timeout;
        this.timeUnit = timeUnit;
    }

    public void execute(Runnable task) {
        synchronized (workers) {
            if (workers.size() <= coreSize) {
                Worker worker = new Worker(task);
                workers.add(worker);
                worker.start();
            } else {
                taskQueue.put(rejectPolicy,task);
            }
        }
    }

    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 e) {
                    e.printStackTrace();
                } finally {
                    task = null;
                }
            }
            synchronized (workers) {
                workers.remove(this);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值