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...");
        });
    }
}

 

完美!

posted @ 2022-02-20 15:39  李东平|一线码农  阅读(666)  评论(0编辑  收藏  举报