手写Java的线程池

手写Java的线程池

简单实现了一个Java的线程池

拒绝策略

/**
 * 拒绝策略
 *
 * @author zhangqi
 * @date 2022/7/26 20:04
 */

@FunctionalInterface
public interface RejectPolicy<T> {
    /**
     * 拒绝策略
     *
     * @param taskQueue 任务队列
     * @param task      任务
     */
    void reject(BlockingQueue<T> taskQueue, T task);
}

阻塞队列

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 自定义的阻塞队列
 *
 * @param <T> 类型
 */
@Slf4j
@SuppressWarnings("unused")
public class BlockingQueue<T> {
    /**
     * 任务队列
     */
    private final Deque<T> deque = new ArrayDeque<>();
    /**
     * 锁 用于多线程获取任务队列中的任务 或 放任务
     */
    private final ReentrantLock lock = new ReentrantLock();
    /**
     * 生产者条件变量  队列满了不能在生产了
     */
    private final Condition fullWaitSet = lock.newCondition();
    /**
     * 消费者条件变量 队列空了不能在生产了
     */
    private final Condition emptyWaitSet = lock.newCondition();
    /**
     * 容量
     */
    private final int capacity;

    /**
     * 构造函数
     *
     * @param capacity 队列大小
     */
    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    /**
     * 获取任务 阻塞 带超时时间
     *
     * @param timeout 超时时间
     * @param unit    时间单位
     * @return 任务
     */
    public T poll(long timeout, TimeUnit unit) {
        long nanos = unit.toNanos(timeout);
        lock.lock();
        try {
            while (deque.isEmpty()) {
                if (nanos <= 0) {
                    return null;
                }
                nanos = emptyWaitSet.awaitNanos(nanos);
            }
            fullWaitSet.signalAll();
            return deque.removeFirst();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        } finally {
            lock.unlock();
        }
    }


    /**
     * 获取任务 阻塞
     *
     * @return 任务
     */
    public T take() {
        lock.lock();
        try {
            while (deque.isEmpty()) {
                emptyWaitSet.awaitUninterruptibly();
            }
            fullWaitSet.signalAll();
            return deque.removeFirst();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 添加任务 阻塞 带超时时间
     *
     * @param element 任务
     * @param timeout 超时时间
     * @param unit    时间单位
     */
    public boolean offer(T element, long timeout, TimeUnit unit) {
        lock.lock();
        long nanos = unit.toNanos(timeout);
        try {
            while (deque.size() == capacity) {
                log.info("等待 [{}]", element);
                if (nanos <= 0) {
                    return false;
                }
                nanos = fullWaitSet.awaitNanos(nanos);
            }
            deque.addLast(element);
            log.info("添加任务 [{}]", element.toString());
            emptyWaitSet.signalAll();
            return true;
        } catch (InterruptedException e) {
            e.printStackTrace();
            Thread.currentThread().interrupt();
            return false;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 添加任务 阻塞
     *
     * @param element 任务
     */
    public void put(T element) {
        lock.lock();
        try {
            while (deque.size() == capacity) {
                log.info("等待 [{}]", element);
                fullWaitSet.awaitUninterruptibly();
            }
            deque.addLast(element);
            log.info("添加 [{}]", element);
            emptyWaitSet.signalAll();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 获取队列大小
     *
     * @return 队列大小
     */
    public int size() {
        lock.lock();
        try {
            return deque.size();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 尝试添加
     *
     * @param rejectPolicy 拒绝策略
     * @param element      任务
     */
    public void tryPut(RejectPolicy<T> rejectPolicy, T element) {
        lock.lock();
        try {
            if (deque.size() >= capacity) {
                rejectPolicy.reject(this, element);
            } else {
                deque.addLast(element);
                log.info("添加 [{}]", element);
                emptyWaitSet.signalAll();
            }
        } finally {
            lock.unlock();
        }
    }
}

线程池

import lombok.extern.slf4j.Slf4j;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 线程池
 *
 * @author zhangqi
 * @date 2022/7/26 20:06
 */
@Slf4j
@SuppressWarnings("unused")
public class ThreadPool {
    /**
     * 阻塞队列
     */
    private final BlockingQueue<Runnable> taskQueue;
    /**
     * 线程集合
     */
    private final Set<Worker> workers = new HashSet<>();
    /**
     * 核心线程数
     */
    private final int coreSize;
    /**
     * 超时时间
     */
    private final long timeout;
    /**
     * 时间单位
     */
    private final TimeUnit unit;
    /**
     * 拒绝策略
     */
    private final RejectPolicy<Runnable> rejectPolicy;

    /**
     * 构造函数
     *
     * @param coreSize      核心线程数
     * @param timeout       超时时间
     * @param unit          时间单位
     * @param queueCapacity 阻塞队列大小
     * @param rejectPolicy  拒绝策略
     */
    public ThreadPool(int coreSize, long timeout, TimeUnit unit, int queueCapacity, RejectPolicy<Runnable> rejectPolicy) {
        this.coreSize = coreSize;
        this.timeout = timeout;
        this.unit = unit;
        this.rejectPolicy = rejectPolicy;
        this.taskQueue = new BlockingQueue<>(queueCapacity);
    }

    /**
     * 执行线程池方法
     *
     * @param task 任务
     */
    public void execute(Runnable task) {
        synchronized (workers) {
            // 没有超过核心线程数
            if (coreSize > workers.size()) {
                Worker worker = new Worker(task);
                log.info("执行任务 = " + worker);
                workers.add(worker);
                worker.start();
                return;
            }
            log.info("加入任务队列 = " + task);
            // 超过核心线程数

            // 1. 死等
            // 2. 等待超时
            // 3. 调用者放弃任务
            // 4. 调用者抛出异常
            // 5. 调用者自己执行任务

            taskQueue.tryPut(rejectPolicy, task);
        }
    }

    /**
     * 工作线程
     */
    private class Worker extends Thread {
        /**
         * 工作线程的任务
         */
        private Runnable task;

        /**
         * 构造方法
         *
         * @param task 任务
         */
        public Worker(Runnable task) {
            this.task = task;
        }

        /**
         * 执行任务
         * 1. task != null 执行task
         * 2. task 执行完成 判读阻塞队列是否为空 不为空 取出尾部 任务执行
         */
        @Override
        public void run() {
            /// 死等
            /// while (Objects.nonNull(task) || Objects.nonNull((task = taskQueue.take()))) {
            // 带超时时间
            while (Objects.nonNull(task) || Objects.nonNull((task = taskQueue.poll(timeout, unit)))) {
                try {
                    task.run();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    task = null;
                }
            }
            synchronized (workers) {
                log.info(" worker 移除" + workers);
                workers.remove(this);
            }
        }
    }
}

测试代码


    public static void main(String[] args) {
        // 死等
        // ThreadPool threadPool = new ThreadPool(2, 1, TimeUnit.SECONDS, 5, BlockingQueue::put);
        // 超时时间
        // ThreadPool threadPool = new ThreadPool(2, 2, TimeUnit.SECONDS, 5, (queue, take) -> queue.offer(take, 1, TimeUnit.SECONDS));
        // 放弃
        // ThreadPool threadPool = new ThreadPool(2, 2, TimeUnit.SECONDS, 5, (queue, take) -> System.out.println("放弃"));
        // 异常
        // ThreadPool threadPool = new ThreadPool(2, 2, TimeUnit.SECONDS, 5, (queue, take) -> {
        //     throw new RuntimeException();
        // });
        // 自己执行
        ThreadPool threadPool = new ThreadPool(2, 2, TimeUnit.SECONDS, 5, (queue, take) -> {
            take.run();
        });
        for (int i = 0; i < 15; i++) {
            int count = i;
            threadPool.execute(() -> {
                log.info("count = " + count);
                Sleep.sleep(2001);
            });
        }
    }

测试结果

2022-07-26 19:57:35.642  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 执行任务 = Thread[Thread-0,5,main]
2022-07-26 19:57:35.645  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 执行任务 = Thread[Thread-1,5,main]
2022-07-26 19:57:35.645  INFO   --- [       Thread-0] c.e.demo.hmjuc.day18.TestThreadPool      : count = 0
2022-07-26 19:57:35.646  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@4f7d0008
2022-07-26 19:57:35.646  INFO   --- [       Thread-1] c.e.demo.hmjuc.day18.TestThreadPool      : count = 1
2022-07-26 19:57:35.646  INFO   --- [           main] c.e.demo.hmjuc.day18.BlockingQueue       : 添加 [com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@4f7d0008]
2022-07-26 19:57:35.648  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@402a079c
2022-07-26 19:57:35.648  INFO   --- [           main] c.e.demo.hmjuc.day18.BlockingQueue       : 添加 [com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@402a079c]
2022-07-26 19:57:35.648  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@59ec2012
2022-07-26 19:57:35.648  INFO   --- [           main] c.e.demo.hmjuc.day18.BlockingQueue       : 添加 [com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@59ec2012]
2022-07-26 19:57:35.648  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@4cf777e8
2022-07-26 19:57:35.648  INFO   --- [           main] c.e.demo.hmjuc.day18.BlockingQueue       : 添加 [com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@4cf777e8]
2022-07-26 19:57:35.648  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@2f686d1f
2022-07-26 19:57:35.648  INFO   --- [           main] c.e.demo.hmjuc.day18.BlockingQueue       : 添加 [com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@2f686d1f]
2022-07-26 19:57:35.648  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@3fee9989
2022-07-26 19:57:35.648  INFO   --- [           main] c.e.demo.hmjuc.day18.TestThreadPool      : count = 7
2022-07-26 19:57:37.651  INFO   --- [       Thread-0] c.e.demo.hmjuc.day18.TestThreadPool      : count = 3
2022-07-26 19:57:37.651  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@73ad2d6
2022-07-26 19:57:37.651  INFO   --- [       Thread-1] c.e.demo.hmjuc.day18.TestThreadPool      : count = 2
2022-07-26 19:57:37.651  INFO   --- [           main] c.e.demo.hmjuc.day18.BlockingQueue       : 添加 [com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@73ad2d6]
2022-07-26 19:57:37.652  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@7085bdee
2022-07-26 19:57:37.652  INFO   --- [           main] c.e.demo.hmjuc.day18.BlockingQueue       : 添加 [com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@7085bdee]
2022-07-26 19:57:37.652  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@1ce92674
2022-07-26 19:57:37.652  INFO   --- [           main] c.e.demo.hmjuc.day18.TestThreadPool      : count = 10
2022-07-26 19:57:39.653  INFO   --- [       Thread-1] c.e.demo.hmjuc.day18.TestThreadPool      : count = 4
2022-07-26 19:57:39.653  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@5700d6b1
2022-07-26 19:57:39.653  INFO   --- [       Thread-0] c.e.demo.hmjuc.day18.TestThreadPool      : count = 5
2022-07-26 19:57:39.654  INFO   --- [           main] c.e.demo.hmjuc.day18.BlockingQueue       : 添加 [com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@5700d6b1]
2022-07-26 19:57:39.654  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@6fd02e5
2022-07-26 19:57:39.654  INFO   --- [           main] c.e.demo.hmjuc.day18.BlockingQueue       : 添加 [com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@6fd02e5]
2022-07-26 19:57:39.654  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@5bcab519
2022-07-26 19:57:39.654  INFO   --- [           main] c.e.demo.hmjuc.day18.TestThreadPool      : count = 13
2022-07-26 19:57:41.657  INFO   --- [       Thread-0] c.e.demo.hmjuc.day18.TestThreadPool      : count = 8
2022-07-26 19:57:41.657  INFO   --- [           main] com.example.demo.hmjuc.day18.ThreadPool  : 加入任务队列 = com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@e45f292
2022-07-26 19:57:41.657  INFO   --- [       Thread-1] c.e.demo.hmjuc.day18.TestThreadPool      : count = 6
2022-07-26 19:57:41.657  INFO   --- [           main] c.e.demo.hmjuc.day18.BlockingQueue       : 添加 [com.example.demo.hmjuc.day18.TestThreadPool$$Lambda$2/1471868639@e45f292]
2022-07-26 19:57:43.658  INFO   --- [       Thread-0] c.e.demo.hmjuc.day18.TestThreadPool      : count = 11
2022-07-26 19:57:43.658  INFO   --- [       Thread-1] c.e.demo.hmjuc.day18.TestThreadPool      : count = 9
2022-07-26 19:57:45.660  INFO   --- [       Thread-1] c.e.demo.hmjuc.day18.TestThreadPool      : count = 12
2022-07-26 19:57:45.660  INFO   --- [       Thread-0] c.e.demo.hmjuc.day18.TestThreadPool      : count = 14
2022-07-26 19:57:48.662  INFO   --- [       Thread-1] com.example.demo.hmjuc.day18.ThreadPool  :  worker 移除[Thread[Thread-0,5,main], Thread[Thread-1,5,main]]
2022-07-26 19:57:48.662  INFO   --- [       Thread-0] com.example.demo.hmjuc.day18.ThreadPool  :  worker 移除[Thread[Thread-0,5,main]]

Process finished with exit code 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值