java多线程之自定义线程池
1.背景
线程池.....大家常用....
自己搞一个,顺便练习一下多线程编程
2.自定义线程代码
2.1.拒绝策略接口
@FunctionalInterface public interface MyRejectPolicy<T> { void reject(MyBlockingQueue<T> queue, T task); }
2.2.自定义阻塞队列
@Slf4j public class MyBlockingQueue<T> { // 1.任务队列 private Deque<T> queue = new ArrayDeque<>(); // 2.容量 private int capacity; // 3.锁 private ReentrantLock lock = new ReentrantLock(); // 4.生产者条件变量 private Condition producerCondition = lock.newCondition(); // 5.消费者条件变量 private Condition consumerCondition = lock.newCondition(); // 构造方法 public MyBlockingQueue(int capacity) { this.capacity = capacity; } // 阻塞获取 public T take() { lock.lock(); try { // 判断是否为空 while (queue.isEmpty()) { try { // 无任务消费者等待 log.info("无任务,消费者等待...."); consumerCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } // 不为空,消费者获取一个任务 T t = queue.removeFirst(); log.info("消费者已获取到任务t={}", t); // 通知生产者放入任务 producerCondition.signal(); return t; } finally { lock.unlock(); } } // 阻塞添加 public void put(T t) { lock.lock(); try { while (queue.size() >= capacity) { try { // 队列已满,生产者等待 log.info("......队列已满,生产者等待"); producerCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } // 放入队列 queue.addLast(t); log.info("......生产者,以将任务放入队列"); // 通知消费者获取任务 consumerCondition.signal(); } finally { lock.unlock(); } } }
2.3.自定义工作线程
@Slf4j public class MyWorkerThread extends Thread { // 线程集合 private HashSet<MyWorkerThread> workerThreadList = new HashSet<>(); // 任务队列 private MyBlockingQueue<Runnable> taskQueue; // 任务对象 private Runnable task; /** * 构造方法 * * @param task */ public MyWorkerThread(HashSet<MyWorkerThread> workerThreadList, MyBlockingQueue<Runnable> taskQueue, Runnable task) { this.workerThreadList = workerThreadList; this.taskQueue = taskQueue; this.task = task; } /** * 执行任务 */ @Override public void run() { // 当【task不为空】时执行当前任务 // 当【task为空】时,从队列中获取任务再执行 while (task != null || ((task = taskQueue.take()) != null)) { try { // 执行任务 log.info("执行当前任务:{}", task); task.run(); } finally { // 将任务设置为空 task = null; } } // 无任务,释放线程 synchronized (workerThreadList) { log.info("无任务,删除当前线程:{}", this); workerThreadList.remove(this); } } }
2.4.自定义线程池
@Slf4j public class MyThreadPool { // 核心线程数 private int coreSize; // 阻塞队列 private MyBlockingQueue<Runnable> taskQueue; // 线程集合 private HashSet<MyWorkerThread> workerThreadList = new HashSet<>(); // 拒绝策略 private MyRejectPolicy<Runnable> rejectPolicy; /** * 线程池构造器 * * @param coreSize * @param rejectPolicy */ public MyThreadPool(int coreSize, MyRejectPolicy<Runnable> rejectPolicy) { this.coreSize = coreSize; this.taskQueue = new MyBlockingQueue<>(coreSize); this.rejectPolicy = rejectPolicy; } /** * */ public void execute(Runnable task) { // 当任务数【没有超过】核心线程数coreSize时,直接给workerThreadList 执行 // 当任务数【超过】核心线程数coreSize时,放入队列 synchronized (workerThreadList) { int size = workerThreadList.size(); if (size < coreSize) { MyWorkerThread workerThread = new MyWorkerThread(workerThreadList, taskQueue, task); workerThread.setName("工作线程-" + (size + 1)); log.info("创建线程对象:{},执行任务:{}", workerThread, task); workerThreadList.add(workerThread); workerThread.start(); } else { taskQueue.put(task); } } } }
3.测试
@Slf4j public class Test01 { /** * 测试自定义的线程池 * @param args */ public static void main(String[] args) { // 创建线程池 MyThreadPool pool = new MyThreadPool(2, (queue, task) -> { queue.put(task); }); // 执行任务 pool.execute(()->{ log.info("执行任务1..."); }); pool.execute(()->{ log.info("执行任务2..."); }); pool.execute(()->{ log.info("执行任务3..."); }); } }