Threads are the basic unit of timing scheduling in the operating system.
The thread pool can be understood as a pool with threads, which is a container. This container can only contain threads. This container has different sizes, it can hold 7 or 8 pieces, or 3 or 4 pieces. The container can also be filled, but there is a maximum value, such as 12. For example, the thread pool here usually contains 5 threads, and can contain up to 12 threads. At this time, there were five people who needed to use the thread pool, so he took away five threads. What if two people came later? He definitely had no threads to use, and he had to wait for those five people to finish using it. But my pool can hold 12. How can I do it if I only have 5 threads? I definitely have to install a few more threads, otherwise it won’t be enough if there are more people. At this time, 2 came, and I am producing 2. The total number of threads reaches 7. At this time, the remaining 2 people do not need to wait and can be used directly. If 6 people come, at this time, my pool may only have capacity for 5 threads. I can produce 5 threads, but there is still one person who has to wait somewhere. I can't let people wait aimlessly. I'll find 5 stools. You can sit there and wait. Then the first wave of five people runs out of threads, and 5 threads are suddenly freed up. The remaining One person can use the thread. At this time, 10 more people came one after another. My thread can only be used by 4 people. The seat can seat five people. What should I do if there is one person left? Or refuse it directly. I don’t have a seat here. You want to It’s definitely uncomfortable to say no without looking elsewhere first, and I have to think of several rejection strategies. . . , I think there are still many people using my thread pool. With so many people using it, what if someone keeps occupying my thread pool? I must find a way to deal with it? Otherwise, one thread can only be used for 1 minute, and it will be recycled immediately after use. If you want to use it again, queue up and wait again. In this way, my thread business is getting better and better. As long as someone uses it, it will keep running.
Is it a bit like a restaurant or a buffet shop? A buffet shop is more visual. In my hotel, as long as there is a seat, people can be seated. When the maximum capacity is reached, the remaining customers can only wait at the door. , a customer in the restaurant comes and waits outside. If there is no more waiting space, the customer will see that there is no space and leave directly. If some people really want to eat, they can wait a little longer. Customers in the restaurant should not eat for too long (usually when there is no seat), about 2 hours, and they will leave after eating.
Based on my description above, I can probably determine what is in the thread pool?
How many threads are installed, how many threads can be installed, how long threads can be retained, thread waiting area, how to reject, create threads
The running of the program must rely on the process, and the actual execution unit of the process is the thread.
Call of services within the system. The system relies on processes to run. There are many services in the system, and there are interactions between services. The running of services relies on threads. Multi-service operation relies on multi-thread operation. The calls and data exchange between services rely on the memory between processes for data interaction. At the same time, threads can also build their own memory space. Relying on resource scheduling and data interaction between processes.
Multiple threads can improve the execution performance of the program. For example, if there is a 90-square-meter house, it takes 30 minutes for one person to clean it, and only 10 minutes for three people to clean it. These three people are the "multithreads" in the program.
In many programs, multiple threads need to be synchronized with each other or mutually exclusive to complete work in parallel.
Threads are more lightweight than processes, so the cost of thread creation and destruction becomes smaller.
Threads improve performance. Although threads are macroscopically parallel, they are microscopically serial. Threads cannot improve performance from a CPU perspective, but if some threads are involved in waiting for resources (such as IO, waiting for input), multi-threading allows other threads in the process to continue executing instead of the entire process being blocked, thus improving CPU utilization. rate, from this perspective the performance will be improved.
In the case of multiple CPUs or multi-cores, using threads is not only macroscopically parallel, but also microscopically parallel.
Multiple threads can improve the execution performance of the program
For example, when eating a buffet, when there are enough seats When there are enough people, the buffet is the most profitable, and it can also improve dining rates and customer satisfaction. If there are 200 people eating and there are 100 dining places, and each person eats for an hour on average, then the 200 people will finish the meal in two hours. If there are only 10 seats, it will take about 20 hours for 200 people to eat. Think about how unhappy the rest of the customers would be if they were waiting anxiously for their meal.
The seats in the buffet are threads. When there are enough threads, more people can eat. However, it does not mean that the more threads, the better. After all, there are not necessarily 200 threads every time. Even if 200 customers come to eat, we still need to evaluate basic hardware factors such as whether there are enough chefs in the restaurant, whether the cleaning lady can clean up, and whether there are enough plates in the restaurant. This is equivalent to system configuration, which requires some essential hardware conditions such as memory and CPU processing.
Creating/destroying threads is accompanied by system overhead. Creating/destroying threads too frequently will greatly affect processing efficiency (as long as the thread continues to execute, it will not be destroyed)
Remember that creating a thread consumes time T1, executing a task consumes time T2, and destroying a thread consumes time T3. If T1 T3>T2, does it mean that it is not cost-effective to open a thread to perform this task? It just so happens that the thread pool caches threads and can use existing idle threads to perform new tasks, avoiding the system overhead caused by T1 T3. Of course, the surviving core threads will also consume CPU resources
Too many concurrent threads will seize system resources and cause blocking.
We know that threads can share system resources. If too many threads are executed at the same time, it may lead to insufficient system resources. In the case of blocking, the use of thread pools can effectively control the maximum number of concurrent threads and avoid the above problems
Perform some simple management of threads
For example: Delayed execution, timed loop execution strategies, etc. can all be well implemented using thread pools
Improve thread utilization Rate
Ensure that it is used when there is business and released when there is no business. Use threads rationally to avoid resource waste
Improve The response speed of the program
If it is managed uniformly by the thread pool, resource allocation is scheduled using a unified scheduling pool. When threads are used, the time-consuming creation and destruction of threads can be avoided. Use threads directly.
Facilitates unified management of thread objects
The thread pool can ensure the unified allocation and management of threads.
Can control the maximum number of concurrencies
The server has an upper limit for thread usage, and thread usage also consumes a lot of resources, so the thread pool It can control thread resources very well and avoid waste.
The ThreadPoolExecutor class is a thread pool class in java, which can be used to pool threads.
// 根据上面的描述大概分析一下线程都需要什么及参数的解析 // corePoolSize 核心线程数,就是上面说的装了多少个线程 // maximumPoolSize 最大线程数,就是上面说的能装多少线程 // keepAliveTime 存活时间,就是上面说的线程可以保留多长时间 // TimeUnit 这个是时间单位,有时、分、秒、天等等,是存活时间的单位 // BlockingQueue<Runnable> 这是一个等待队列,就是上面显示的线程等待区 // ThreadFactory 线程工厂,就是上面描述的如何创建线程,由谁创建 // RejectedExecutionHandler 拒绝策略,就是上面显示的如何拒绝,是直接拒绝还是婉拒 public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue) public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory) public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)
As you can see, it requires the following parameters:
import java.util.concurrent.*; public class ThreadTest { public static void main(String[] args) { ExecutorService threadPoolExecutor = new ThreadPoolExecutor(3, 5, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory()); for (int i = 0; i < 20; i++) { int finalI = i; threadPoolExecutor.submit( ()->{ System.out.println(Thread.currentThread().getName() + "========" + finalI); }); } threadPoolExecutor.shutdown(); } }
pool-1-thread-1========0
pool-1-thread-3========2
pool-1-thread-3========4
pool-1-thread-2========1
pool-1-thread-3========5
pool-1-thread-2========8
pool-1-thread-5========7
pool-1-thread-1========3
pool-1-thread-4========6
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@61e717c2 rejected from java.util.concurrent.ThreadPoolExecutor@66cd51c3[Running, pool size = 5, active threads = 2, queued tasks = 0, completed tasks = 7]
at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063)
at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1379)
at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
at com.halo.communication.ThreadTest.main(ThreadTest.java:10)
执行的线程数超过了线程池可容纳的大小,线程池使用默认拒绝策略拒绝多余线程执行,然后开始出现异常处理。上面执行的线程数到thread-5,5是线程池的默认最大线程数。然后执行for循环20次,进行执行到8的时候出现异常,说明线程池已经超载满负荷执行,所以线程池执行拒绝策略。
The above is the detailed content of What are the principles, usage, and performance optimization methods of Java thread pool?. For more information, please follow other related articles on the PHP Chinese website!