Completely buttoned thread pool - build (1) thread pool model

Outline

Do the back-end of the thread pool should know, even if you have not personally used, it must also be heard or understood before. Sometimes go in-depth understanding, the result is often felt themselves to understand, over a period of time to forget. Because in the daily development, we do not need to use the thread pool, many tools and frameworks are used to write, we directly tune the interface gets the job done.

A lot of things did not personally practice and in-depth thought about, just look at the articles and books it is impossible to truly understand. I read it several times before the article related to the thread pool, then over half a year almost forgotten, look again, the result was not really understood. So, I intend to hands-on about it, since less than the usual development time, I'll do a project yourself to spend.

Just do it, I chose a distributed lock Redis as a practiced hand project, which has a regular renewal function is to use thread pool task timed run submitted to key renewal, details do not say, think You can see this understanding implement -Redisson Redis distributed locks .

When implementing Redis renewal function, while watching how others achieve regular tasks, while watching the source thread pool. This time I seem to open the door to a new world, a thorough understanding of the logic thread pool running, but also to understand some art thread pool design.

Next, I would like to a designer's point of view, take you from zero to design and implement a thread pool, step by step, to achieve a thorough understanding of the thread pool as well as a number of art and design.

Purpose and significance of the thread pool appears

We need to understand that any technology is to solve the problems arise. Then the thread pool appears to solve the problem, the answer is: 解决了线程资源复用的问题.

If there is no thread pool, we are dealing with a task will open a new thread to execute when the task is completed, the thread is stopped. If this task is repetitive, you can not create a new thread to a bar, more than a waste, and the thread is a scarce resource, create a duplicate destroy very time-consuming.

With the thread pool, we can establish a few fixed thread. There are tasks to wake the idle thread to handle the task processing continues after the completion of processing of subsequent tasks, if the task is not temporary, can thread to sleep, and then wake up when there is a new task. Such an action would be a more efficient use of thread resources, improve system concurrency efficiency.

Task: abstract unit of work

In the program, we are around 任务执行to construct, the task is usually some abstract unit of work. For example, you can put a http request as a task, a task as interaction with the database and so on. In the thread pool, something we have to deal with abstract into a 任务单元, which can simplify the structure of the thread pool, in order to build a better model of the thread pool.

Thread: abstract worker

In the thread pool, we can put each thread as a worker, namely "worker" means. It will continue to try to get the task to perform, if no job, sleep or do other processing.

Thread pool of functional design

Then, the thread pool usually have and what features it offers, where the core functional requirements to the list of about:

The opening and closing of the thread pool

Thread pool as a tool needs to have its own life cycle, it can be abstracted into three:

  • Open state
  • Operating status
  • End state

Where things end state of the thread pool to be considered and treated more, the interface is closed after executing the thread pool:

  • Running task how to deal with?
  • Task in the task queue of how to deal with?
  • At this point the thread pool whether it can continue to add tasks?

These things are to be considered and processed. In the Java ExecutorServiceprovides two interfaces is closed

  • shutdown : Orderly shutdown, the task has been submitted will be processed individually, but will not accept any new tasks
  • shutdownNow : Attempts to stop all actively executing tasks, give up the task waiting in the queue, and return to the task list is waiting to be executed

Build and manage threads

Thread pool thread how to build, how to build after the administration, is a fixed number or dynamic building. Here are a few modes:

  1. 固定的线程数量 : When the thread pool starts to build a fixed number of thread pool, and will not close any thread
  2. 动态构建线程: Do not create any new threads start, when there comes the task will be to create a thread. If the task is relatively small, it will not continue to create a new thread if the task is more, the number of threads continue to build until the number reaches the maximum value.
  3. 有闲置期限的线程: Thread when building there will be a period of inactivity when idle longer than this, the thread will be recycled. The more commonly used in the database connection pool to
  4. 单个线程 : Only one thread, the task performed chronologically submitted.

Task Management

In the thread pool, it will create a task queue, when there is no idle thread, the new task will be placed in the queue, waiting thread.

Thread pool to provide an interface for the task.

In addition, many tasks will be to deal with the results as a return value, then the task must be completed after a processing mechanism, do some action when the task is completed. (Here it must relate to the FutureTaskconcepts of)

Tasks related to the following functions:

  • The task of submitting
  • Tasking results
  • Task cancellation and interruption

Construction of the thread pool model

Sort out some of the basic functions of the thread pool and the point to be considered, then the execution thread pool is what, how to design it. Do not talk nonsense, directly on the map:

View when a new task whether there is an idle thread, if any, direct treatment, if not then put the task queue, waiting threads.

In fact, comb thread pool, you can find its logic is not complicated, complex deal with various situations, such as how thread management, how to deal with the task to cancel, interrupt threads how to deal with and so on, as well as handle a variety of concurrent operations.

Use code implements a simple thread pool

Then implement a fixed number of thread pool to achieve the following functions:

Thread pool to provide interface

  • The task of submitting

Internal thread pool to achieve the function

  • To achieve the task queue
  • Thread Management

We temporarily core functionality of a simple thread pool to achieve, understand the logic execution thread pool, slowly add the other after.

Create a task unit

The first unit to achieve the task, directly implement Runnablethe interface can be.

Of course, you can not implement Runnablean interface, just write a class, an interface to an execution, but do so common thread pool is not enough, or directly implement Runnablethe interface, the next task any implementation of the interface can be handed over to the thread pool to perform.

static class Task implements Runnable{
    
        private int tag;

        public Task(int tag){
            this.tag = tag;
        }

        @Override
        public void run() {
            System.out.printf("任务 %d 开始执行 \n",tag);
            System.out.printf("任务 %d 执行中 \n",tag);
            System.out.printf("任务 %d 执行结束\n",tag);
        }
}
复制代码

Achieve thread pool

Detailed explanation in the comments, see comments on it

package steap1;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.locks.ReentrantLock;

public class ThreadPoolExecutor {

    //工作线程数组
    private Worker[] workers;

    //任务阻塞队列,是线程安全的,里面每个操作都会加锁处理
    private BlockingQueue<Task> queue;

    // 当前工作线程的数量
    private int workerSize = 0;

    //线程池最大的工作线程数量
    private int poolSize;

    public ThreadPoolExecutor(int poolSize, BlockingQueue<Task> queue) {
        this.poolSize = poolSize;
        this.workers = new Worker[poolSize];
        this.queue = queue;
    }

    //任务添加接口
    public void execute(Task task) {
        //如果线程池的线程数量小于最大值,则添加线程
        //否则将任务放入队列中
        if (workerSize < poolSize) {
            addWorker(task);
        } else {
            this.queue.add(task);
        }
    }

    //添加worker工作线程,并立即执行
    private synchronized void addWorker(Task task) {
        //这里做个双重判定,判定线程数量是否小于最大值
        if (workerSize >= poolSize) {
            this.queue.add(task);
            return;
        }

        //构建worker,并启动线程
        workers[workerSize] = new Worker(task);
        workers[workerSize].t.start();

        workerSize++;
    }

    //实际运行的代码
    void runWorker(Worker worker){
        Task task =(Task) worker.task;
        try {
            while (true){
                //线程在这个循环中不断的获取任务来执行
                // queue.task() 方法是一个线程安全的阻塞方法
                //如果队列没有任务,那么所有工作线程都会在这里阻塞,等待获取可用的任务
                if(task == null){
                    task = this.queue.take();
                }
                task.run();
                task = null;
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    
    //工作线程包装类
    private class Worker implements Runnable {
        private Runnable task;

        final Thread t;

        public Worker(Runnable task) {
            this.task = task;
            this.t = new Thread(this);
        }

        @Override
        public void run() {
            runWorker(this);
        }
    }

    //任务类
    static class Task implements Runnable {

        private int tag;

        public Task(int tag) {
            this.tag = tag;
        }

        @Override
        public void run() {
            System.out.printf("任务 %d 开始执行 \n", tag);
            System.out.printf("任务 %d 执行中 \n", tag);
            System.out.printf("任务 %d 执行结束\n", tag);
        }
    }
}
复制代码

Simple to use

    public static void main(String[] args){
        ThreadPoolExecutor executor = new ThreadPoolExecutor(8,new LinkedBlockingQueue<>());
        for(int i=0;i<1000;i++){
            executor.execute(new ThreadPoolExecutor.Task(i));
        }
    }
复制代码

Results of the

任务 923 开始执行 
任务 923 执行中 
任务 923 执行结束
任务 912 开始执行 
任务 912 执行中 
任务 912 执行结束
复制代码

to sum up

Thus, a simple thread pool on the preparation is complete, the thread pool main functions are realized, throughout the implementation process is also carried out a detailed description.

In fact, there's a lot of things I did not write on, thread cancellation lifecycle management tasks and threads interrupts and so on, these things in the next chapter in improving it.

Attach the end of the project source code , this chapter in step1the.

Guess you like

Origin juejin.im/post/5df8ca3a6fb9a01660499300