造轮子-手写java线程池

今天学习了JDK中的线程池,梳理了一下线程池的流程机制,尝试着写个简单的线程池

package com.hobson.day2;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

/**
 * 重复造轮子-线程池
 *
 * @author haibin.tang
 * @create 2020-04-13 2:59 PM
 **/
public class WheelThreadPool implements Executor {
    /**
     * 核心线程数
     */
    private int coreThreadSize;
    /**
     * 最大线程数
     */
    private int maxThreadSize;
    /**
     * 任务队列
     */
    private static BlockingQueue<Runnable> taskBlockQueue;
    /**
     * 工作线程: 核心线程+非核心线程
     */
    private ConcurrentLinkedQueue<Worker> workers = new ConcurrentLinkedQueue<>();

    public WheelThreadPool(int coreThreadSize, int maxThreadSize, BlockingQueue<Runnable> taskBlockQueue) {
        this.coreThreadSize = coreThreadSize;
        this.maxThreadSize = maxThreadSize;
        WheelThreadPool.taskBlockQueue = taskBlockQueue;
    }

    @Override
    public void execute(Runnable command) {
        assert command != null;
        //如果核心线程大于工作线程 则新建线程
        if (coreThreadSize > workers.size()) {
            doJob(command, true);
        }
        //如果工作线程小于最大线程数 则新建线程
        else if (workers.size() < maxThreadSize){
            doJob(command, false);
        }
        //工作线程>= 最大线程数,则把任务放入队列
        else {
            taskBlockQueue.add(command);
        }
    }

    private void doJob(Runnable task, boolean coreThread) {
        Worker worker = new Worker(task, coreThread);
        workers.add(worker);
        worker.getThread().start();
    }

     void runTask(Worker worker) {
        worker.getTask().run();
        Runnable task;
        //自旋
        for (;;) {
            try {
                if (!worker.isCoreThread()) {
                    //如果是非核心线程 则使用超时获取 任务
                    task = taskBlockQueue.poll(2000, TimeUnit.MICROSECONDS);
                    //如果任务未获取到 则把此工作线程移除队列
                    if (task == null) {
                        workers.remove(worker);
                        worker = null;
                        return;
                    }
                } else {
                    //如果是核心线程 则使用take方法,该方法会阻塞 到获取到任务为止
                    task = taskBlockQueue.take();
                }
                task.run();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private class Worker implements Runnable {
        private Runnable task;
        private boolean coreThread;
        private Thread thread;
        Worker(Runnable task, boolean coreThread) {
            this.task = task;
            this.coreThread = coreThread;
            thread = new Thread(this);
        }
        boolean isCoreThread() {
            return coreThread;
        }
        @Override
        public void run() {
            runTask(this);
        }

        Runnable getTask() {
            return task;
        }
        Thread getThread() {
            return thread;
        }

        @Override
        protected void finalize() throws Throwable {
            System.out.println(String.format("work[%s]被gc", thread.getName()));
        }
    }
}
package com.hobson.day2;

import java.util.concurrent.LinkedBlockingQueue;

/**
 * @author haibin.tang
 * @create 2020-04-13 4:46 PM
 **/
public class Day2Main {

    public static void main(String[] args) {
        WheelThreadPool pool = new WheelThreadPool(2, 5, new LinkedBlockingQueue<>());
        for (int index = 0; index < 100; ++index) {
            int finalIndex = index;
            pool.execute(() -> {
                try {
                    Thread.sleep(2000);
                    System.out.println(Thread.currentThread() + "-index -->> " + finalIndex);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }
}

运行结果如下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值