This is the 20th day of my participation in the August Text Challenge.More challenges in August

The thread pool

There are three benefits to using thread pools properly.

First: reduce resource consumption. Reduce the cost of thread creation and destruction by reusing created threads.

Second: improve response speed. When a task arrives, it can be executed immediately without waiting for the thread to be created.

Third: improve thread manageability. Threads are scarce resources. If created without limit, they consume system resources and degrade system stability. Thread pools can be used for uniform allocation, tuning, and monitoring.

ThreadPoolExecutor performs the execute method in four different ways. 1) If there are fewer threads currently running than corePoolSize, a new thread is created to perform the task (note that this step requires a global lock). 2) Add the task to BlockingQueue if the number of running threads is equal to or greater than corePoolSize. 3) If the task cannot be added to the BlockingQueue (the queue is full), a new thread is created to process the task (note that this step requires a global lock). 4) if you create a new thread will make the currently running thread beyond maximumPoolSize, task will be rejected, and call the RejectedExecutionHandler. RejectedExecution () method.

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    // If the number of threads is less than the base number, a thread is created and the current task is executed
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    // If the number of threads is greater than or equal to the basic number of threads or thread creation fails, the current task will be put to the work queue.
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null.false);
    }
    // If the thread pool is not running or the task cannot be queued, and the current number of threads is less than the maximum number of threads allowed, a thread is created to execute the task.
    else if(! addWorker(command,false))
        / / throw RejectedExecutionException anomalies
        reject(command);
}
Copy the code

The overall design idea for ThreadPoolExecutor to take these steps is to avoid acquiring global locks as much as possible when executing the execute() method (which would be a serious scalability bottleneck). After ThreadPoolExecutor has warmed up (the number of threads currently running is greater than or equal to corePoolSize), almost all execute() method calls execute Step 2, which does not require a global lock.

Threads in the thread pool perform tasks in two ways, as follows.

1) When a thread is created in the execute() method, it is told to execute the current task.

2) After the thread completes task 1, it repeatedly fetches tasks from BlockingQueue to execute.

Worker thread: When the thread pool creates a thread, it will encapsulate the thread as Worker thread. After the Worker completes the task, it will cycle to obtain the task in the work queue for execution. We can see this in the run() method of the Worker class:

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        while(task ! =null|| (task = getTask()) ! =null) {
            w.lock();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted. This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            if((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && ! wt.isInterrupted()) wt.interrupt();try {
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    task.run();
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally{ afterExecute(task, thrown); }}finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally{ processWorkerExit(w, completedAbruptly); }}Copy the code