Server-side applications, such as databases and Web servers, need to handle high-concurrency, short-time requests from clients, so frequently creating the threads needed to process these requests is a very resource-intensive operation. The conventional approach is to create a new thread for a new request, and while this approach seems easy to implement, it has significant disadvantages. It takes more time to create a new thread for each request and more system resources to create and destroy the thread. Therefore, creating too many JVMS at the same time can cause the system to run out of memory, requiring a limit on the number of threads to be created, that is, the use of thread pools.

What is a thread pool in Java?

Thread pool technology is a thread reuse technology, using previously created threads to perform the current task, and provides a solution to the problem of thread cycle overhead and resource conflict. Because the thread already exists when the request arrives, the delay caused by the thread creation process is eliminated, resulting in a faster response from the application.

  • Java provides an Executor framework centered around the Executor interface and its subinterfaces ExecutorService and ThreadPoolExecutor. Using Executor, threading tasks can be completed by simply implementing the Runnable interface and handing it off to the Executor.
  • Encapsulate the thread pool for you and focus your programming tasks on the implementation of specific tasks rather than the implementation mechanism of threads.
  • To use a thread pool, we first create an ExecutorService object, and then pass a set of tasks to it. The ThreadPoolExcutor class sets the thread pool initialization and maximum thread capacity.

The figure above shows that the thread pool initializes with three threads and there are five task objects waiting to run in the task queue.

Executor thread pool method

methods describe
newFixedThreadPool(int) Create a thread pool with a fixed number of threads. The int argument represents the number of threads in the pool
newCachedThreadPool() Create a cacheable thread pool that has the flexibility to reclaim idle threads. If no idle thread exists, a new thread is created to process the task.
newSingleThreadExecutor() Create a single threaded thread pool that uses only one worker thread to perform tasks
newScheduledThreadPool Create a fixed – length thread pool to support scheduled and periodic task execution

In the case of a fixed thread pool, if the executor is currently running all threads, the pending task is placed in the queue and executed when the thread becomes idle.

Thread pool example

In the following sections, we will introduce the executor executor for thread pools.

Create a thread pool to handle the steps to follow for tasks

  1. Create a task object (implementing the Runnable interface) that performs specific task logic
  2. Create a thread pool by using Executors
  3. Assign tasks to the ExecutorService for task processing
  4. Stop the Executor thread pool
Class Task implements Runnable {private String name; private String name; public Task(String s) { name = s; Public void run() {try{for (int I = 0;} public void run() {try{for (int I = 0; i<=5; i++) { if (i==0) { Date d = new Date(); SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss"); Println (" task initialization "+ name +" =" + ft.format(d)); Else {Date d = new Date();} else{Date d = new Date(); SimpleDateFormat ft = new SimpleDateFormat("hh:mm:ss"); System.out.println(" task executing "+ name +" =" + ft. Format (d)); } thread.sleep (1000); } system.out. println(" task completed "+ name); } catch(InterruptedException e) { e.printStackTrace(); }}}Copy the code

The test case

Public class ThreadPoolTest {static final int MAX_SIZE = 3; Public static void main (String[] args) {// Create 5 tasks Runnable R1 = new Task(" Task 1"); Runnable r2 = new Task("task 2"); Runnable r3 = new Task("task 3"); Runnable r4 = new Task("task 4"); Runnable r5 = new Task("task 5"); / / the second step: create a fixed number of threads in the thread pool, the number of threads for MAX_SIZE ExecutorService pool = Executors. NewFixedThreadPool (MAX_SIZE); // Step 3: Assign tasks to the ExecutorService for task processing: Pool.execute (R1); pool.execute(r2); pool.execute(r3); pool.execute(r4); pool.execute(r5); // Step 4: Close the thread pool pool.shutdown(); }}Copy the code

Example Execution Result

Task initialization task 1 = 05:25:55 task initialization task 2 = 05:25:55 task initialization task 3 = 05:25:55 task executing task 3 = 05:25:56 task executing task 1 = 05:25:56 Task 2 = 05:25:56 Task being Executed Task 1 = 05:25:57 Task being Executed Task 3 = 05:25:57 Task being Executed Task 2 = 05:25:57 Task being executed Task 3 = 05:25:58 Task 1 = 05:25:57 Task being Executed Task 2 = 05:25:57 Task being executed Task 3 = 05:25:58 Task executing task 1 = 05:25:58 task executing task 2 = 05:25:58 task executing task 2 = 05:25:59 task executing task 3 = 05:25:59 task executing task 1 = 05:25:59 Task 1 = 05:26:00 Task 2 = 05:26:00 Task 3 = 05:26:00 Task Completed Task 3 Task completed Task 2 Task completed Task 1 Task initialized task Task 5 = 05:26:01 Task initialization Task 4 = 05:26:01 Task executing Task 4 = 05:26:02 Task executing Task 5 = 05:26:02 Task executing Task 4 = 05:26:03 Task executing Task Task 5 = 05:26:03 A task is executing Task 5 = 05:26:04 A task is executing Task 4 = 05:26:05 A task is executing Task 5 = 05:26:05 A task is executing task Task 5 = 05:26:06 Task Execution Completed Task 4 Task execution completed Task 5Copy the code

As shown in the program execution results, task 4 or task 5 is executed only when the threads in the pool become idle. Until then, additional tasks are placed in the queue to be executed.

The thread pool performs the first three tasks, and the pool is cleared for tasks 4 and 5

One of the main advantages of using this thread pool approach is that if you want to handle 10,000 requests at a time, but you don’t want to create 10,000 threads, you can avoid downtime due to overuse of system resources. You can use this method to create a pool of 500 threads, and you can submit 500 requests to the pool. ThreadPool will now create up to 500 threads to handle 500 requests at a time. After either thread’s process completes, ThreadPool internally assigns the 501st request to that thread and continues to do the same for all remaining requests. Thread pool is an effective solution to ensure the stable running of program under the condition of system resource shortage.

Considerations and tuning for using thread pools

  1. Deadlocks: While deadlocks can occur in any multithreaded program, thread pools introduce another case of deadlocks in which all executing threads are waiting for the results of some blocking thread in the queue, causing the thread to be unable to continue.
  2. Thread leakage: Thread leakage occurs if threads in the thread pool do not return correctly when the task is completed. For example, if a thread throws an exception and the pool class does not catch it, the thread exits the exception and the size of the thread pool is reduced by one. If this happens multiple times, the thread pool will eventually become empty and no threads will be available to perform other tasks.
  3. Frequent thread rotation: If the thread pool size is very large, context switching between threads can be a waste of time. So larger thread pools are not always better, as system resources allow.

Thread pool size optimization: The optimal size of a thread pool depends on the number of processors available and the nature of the tasks to be processed. For CPU-intensive tasks, assuming the system has N logical processing cores, a maximum thread pool size of N or N+1 will achieve maximum efficiency. For I/O intensive tasks, the ratio of request wait time (W) to service processing time (S) needs to be considered. The maximum size of the thread pool is N*(1+ W/S) to achieve maximum efficiency.

Do not use the above summary dogma, need to be flexible Settings and tuning according to your application task handling type, including testing experiments.

Welcome to my blog, where there are many fine collections

  • This article is reprinted with a credit (must be accompanied by a link, not only the text) : Antetokounmpo blog.

Feel helpful to you, help me like, share! Your support is my inexhaustible creative power! . In addition, the author recently a period of time output as follows boutique content, looking forward to your attention.

  • Spring Boot2.0 by Hand
  • Spring Security- JWT-OAUTH2
  • RBAC Authority Management System for Actual Combat Front-end and Back-end Separation
  • “Actual SpringCloud Micro-service from Bronze to King”
  • VUE Series