White architect 19- growth path to achieve its own thread pool

Implement own thread pool

Inside the case you can download from gitHub down to look at their own
address: https: //github.com/JolyouLu/Juc-study.git Code at Juc-MyExecutor

The nature of the thread pool

Before implementing a thread pool we have to understand the nature of the thread pool is doing, he solved the problem in the use of multiple threads when the thread is not open, the better, if we Thread created and used by the new thread can not be reused, frequent use of new heap easily full speed up the frequency of the CG (garbage collection), every CG JVM stops all work waiting CG end, making use of multi-threading did not get the desired results, the thread pool he was quite multithreaded containers, thread pool thread to be reusable, and can control the current number of running threads, waiting for the number of threads, the extra threads and other problem-solving strategies.

Thread pool metaphor

We want to achieve a thread pool that first of all we need to know, to realize what a thread pool needs, we can thread pool metaphor to do a factory, you are the boss, you want to open a line of what it needs, raw materials machinery, formal work number, temporary the number of workers, salaried status, refused to single strategy

Raw machine: As long as there are raw materials necessary to produce machine, workers will need to get the raw materials to assemble, as long as there is a considerable production thread will execute threads

Raw materials staging area: raw material production speed of the machine is certainly faster than the speed of assembly workers, formal workers if full of people so raw materials will be stacked in the area, and that area is filled with raw material if it is that if you are the boss you need consider hire some temporary workers, and considerable thread pool queue, if the core thread is full then the task will be added to the queue, if the queue is full, then the future will create a new thread execution

Formal workers: formal long-term work is to go to work every job you have to work very core capacity even if the thread pool tasks are executed over the core thread ran in the background still empty

Temporary: If you suddenly work workload it to be fast, so the plant will recruit temporary workers, temporary workers and permanent workers finished the different tasks will be fired, the equivalent of the maximum capacity of the thread pool

Worker status: If these formal workers come to work these days, but there is no need to do any work that is not considered to have fired them, reduce capital destruction

Refused to single strategy: if our raw materials staging area is full, also recruit temporary workers full, it should refuse to accept new orders to stop raw materials, workers on hand to make things done, to avoid the waste of raw materials

JDK thread pool

After the above analogy we look at JDK thread pool Interface

public ThreadPoolExecutor(int corePoolSize, //核心容量
                          int maximumPoolSize, //最大容量
                          long keepAliveTime, //超时时间
                          TimeUnit unit, //时间单位
                          BlockingQueue<Runnable> workQueue) { //线程队列
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);
}

My initial a thread pool

//我这里初始了一个 核心容量是10 最大容量是50 核心线程空闲0秒就去处 LinkedBlockingQueue队列的线程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 50, 0L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());

The maximum capacity of the core capacity of the thread timeout I believe we all understand, then I want to say here that a queue

JDK thread pool queue

ArrayBlockingQueue: When creating a need to pass the length, you can define the length of the queue, the task when received, if the current thread has run over the core task will then join the queue, if the queue is also filled up, the CPU creates temporary thread mission, if temporary open more than the maximum number of threads that capacity, an error occurs

LinkedBlockingQueue: This is an unbounded queue, the queue length is Integer.MAX_VALUE, that is infinite, then if the current thread has run over the core task will then join the queue, because this queue is infinite, it is never full , meaning that after the use of the queue after you set the maximum capacity is meaningless, because only the queue is full CPU thread will go to create a temporary mission, but you will never queue is full

SynchronousQueue: This synchronization queue, the queue is simply is simply not the length, but it did put on a look fit any task, because the queue is simply not the capacity, then if the current core thread running full, and this queue fit something, then it will create a temporary thread CPU tasks, if temporary open more than the maximum number of threads that capacity, an error occurs

DelayQueue: Delayed within queue element must implement the interface, which means you pass in task must implement the interface Delayed, when the queue is receiving a task, first of all first-team only reached the specified delay time, will perform the task

Thread Pool workflow

Here Insert Picture Description

First, we main thread (main) will execute a method call, we will go to any judge some of the current thread pool core capacity, if the core is not full capacity it will call the method addWork the task is added to the core thread, if a full core thread the task will then offer to our waiting queue, waiting for the core thread has a vacancy in the take out from the queue, if the queue is also filled up then this will create a non-core container capacity to run these tasks, if non-core vessels also full and then have the task to come, will refuse to use strategies

Implement own thread pool

Executor interface

All thread pool base class that provides an interface execute

public interface Executor {

    void execute(Runnable task);

}

ThreadPoolExecutor implementation class

Because it is simple to achieve so I did not use so multi-layered inheritance

public class ThreadPoolExecutor implements Executor {

    //核心容量
    private volatile int corePollSize;
    //最大容量
    private volatile int maximumPoolSize;
    //核心线程超时销毁
    private volatile long keepAliveTime;
    //描述是否需要超时销毁
    private volatile boolean allowCoreThreadTimeOut;
    //当前数量
    private final AtomicInteger ctl = new AtomicInteger(0);
    //队列
    private BlockingQueue<Runnable> workQueue;

    //初始线程池
    public ThreadPoolExecutor(int corePollSize, int maximumPoolSize, BlockingQueue<Runnable> workQueue) {
        this.corePollSize = corePollSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
    }

    public ThreadPoolExecutor(int corePollSize, int maximumPoolSize, long keepAliveTime, boolean allowCoreThreadTimeOut, BlockingQueue<Runnable> workQueue) {
        this.corePollSize = corePollSize;
        this.maximumPoolSize = maximumPoolSize;
        this.keepAliveTime = keepAliveTime;
        if (keepAliveTime>0){
            allowCoreThreadTimeOut= true;
        }
        this.allowCoreThreadTimeOut = allowCoreThreadTimeOut;
        this.workQueue = workQueue;
    }

    /**
     * 暴露接口 接收 task任务
     * @param command
     */
    @Override
    public void execute(Runnable command) {
        if (command == null){
            throw new NullPointerException();
        }
        int c = ctl.get();
        if (c < corePollSize){ //判断是不是小于核心
            addWorker(command,true); //把任务添加到核心容量
        }else if (workQueue.offer(command)){ //如果核心满了 添加到队列中 成功true 失败flash
            addWorker(null,false); //传空
        }else {
            reject(command); //如果队列也满了 使用拒绝策略
        }

    }

    //添加任务内容
    private void addWorker(Runnable task,boolean core) {
        if(core){//如果true,表示使用核心容量,计数加1
            ctl.incrementAndGet();
        }
        Worker worker = new Worker(task);//传入task任务
        worker.thread.start();//调run方法
    }

    //拒绝策略 方法
    private void reject(Runnable command) {
        RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler();
        rejectedExecutionHandler.rejectedExecution(command);
    }

    /**
     * 工作内容 内部类
     */
    class Worker extends ReentrantLock implements Runnable{
        private Runnable firstTask;
        private Thread thread;

        //初始任务
        public Worker(Runnable firstTask) {
            this.firstTask = firstTask;
            thread = new Thread(this);
        }

        @Override
        public void run() {
            runWork(this);//调用具体的执行
        }

        //具体的执行任务方法
        private void runWork(Worker w) {
            //上锁
            try {
                w.lock();
                Runnable task = w.firstTask;
                //判断task 如果不为空,或者去队列取task 不为空
                if (task!=null || (task=getTask())!= null){
                    task.run(); //执行run方法
                }
            }finally {
                processWorkerExit(w); //执行完重复使用
                w.unlock();
            }
        }

        //往worker传null 达到重复使用效果
        private void processWorkerExit(Worker w){
            addWorker(null,false);
        }

        private Runnable getTask() {
            try {
                if (workQueue.isEmpty()){
                    return null;
                }
                //三目表达式 如果开启了超时 ?传入超时时间获取队列如果是超时了返回null ? 否则直接返回队列元素
                Runnable r = allowCoreThreadTimeOut ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS): workQueue.take();
                if (r != null){
                    return r;
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    /**
     * 拒绝策略 内部类
     */
    class RejectedExecutionHandler{
        public void rejectedExecution(Runnable command){
            throw new RejectedExecutionException("这个task"+command+"被拒绝");
        }
    }
}

Test Methods

public class Test {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0,5,new LinkedBlockingDeque<>());
        for (int i=0;i<10;i++){
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("MyThreadPoolExecutor");
                }
            });
        }
    }
}

Published 33 original articles · won praise 22 · views 935

Guess you like

Origin blog.csdn.net/weixin_44642403/article/details/104577042