1. Thread pool and thread performance comparison
In the case of single thread, the speed of processing tasks is greatly improved compared with the performance of using thread pool. Thread pool can be reused inside. After the thread processes the task, it can return to the thread pool to process other tasks, which greatly reduces thread destruction. and creation time.
Several thread pools that come with java:
ExecutorService executorService = Executors.newCachedThreadPool(); ExecutorService executorService1 = Executors.newFixedThreadPool(100); ExecutorService executorService2 = Executors.newSingleThreadExecutor(); ExecutorService executorService3 = Executors.newScheduledThreadPool(10);The construction parameters of the thread pool above are all created with ThreadPoolExecutor, but the parameters used are different.
The construction method used by newCachedThreadPool: corresponding parameters (number of core threads, maximum number of threads, thread survival time, thread survival time unit, queue), newCachedThreadPool has only 0 core threads, and the number of temporary threads can be infinite, so its execution efficiency is very high , SynchronousQueue is a typical producer consumer model, which is equivalent to an outsourcing company.
new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>())The construction method used by newCachedThreadPool: the number of core threads and the number of temporary threads are both customized. The LinkedBlockingQueue queue is an unbounded blocking queue, which is equivalent to waiting for task processing indefinitely, but the efficiency is very low. Equivalent to a state-owned enterprise. new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit. MILLISECONDS, new LinkedBlockingQueue<Runnable>())The construction method used by newSingleThreadExecutor: the number of core threads and the number of temporary threads are both 1, which is equivalent to one person handling countless tasks. The efficiency is very fast when the task can be processed quickly, but it will be slow when the task needs to be processed. It seems very inefficient. It is equivalent to a private enterprise, and everything is done by one person. new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit. MILLISECONDS, new LinkedBlockingQueue<Runnable>()))The thread pool most likely to have OOM: newCachedThreadPool, which is not an unbounded queue, will report OOM when it reaches the maximum value of memory
The previous three cases are not recommended by Ali’s specifications, but the above three can be used in businesses that cannot reach the top value of memory. Ali recommends custom thread pool ThreadPoolExecutor
1.1 Comparison of thread pools in practice
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadDemo {
public static void main(String[] args) {
//定义3个线程池
ExecutorService executorService = Executors.newCachedThreadPool();//很快
ExecutorService executorService1 = Executors.newFixedThreadPool(100);//不快不慢
ExecutorService executorService2 = Executors.newSingleThreadExecutor();//最慢
//定义100个任务给线程池处理对比处理性能
long begin = System.currentTimeMillis();
for(int i=0;i<100;i++){
executorService2.submit(new Task());
}
executorService.shutdown();
long end = System.currentTimeMillis();
System.out.println("处理时间:"+(end-begin)/1000+"秒");
}
}
class Task implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"处理完任务");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1.2 ThreadPool Executor combat
/**
* 第31个任务会拒绝任务
*/
public class ThreadDemo {
public static void main(String[] args) {
//定义ThreadPoolExecutor
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 30, 0, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10));
//定义100个任务给线程池处理对比处理性能
long begin = System.currentTimeMillis();
for(int i=0;i<100;i++){
threadPoolExecutor.submit(new Task());
}
threadPoolExecutor.shutdown();
long end = System.currentTimeMillis();
System.out.println("处理时间:"+(end-begin)/1000+"秒");
}
}
class Task implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"处理完任务");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1.3 Interview question 1: Custom thread pool parameters
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {corePoolSize: number of core threads
int maximumPoolSize: the maximum number of threads
long keepAliveTime: Temporary thread survival time
TimeUnit unit: Temporary thread survival unit
BlockingQueue<Runnable> workQueue: task queue
ThreadFactory threadFactory: general custom factory class
RejectedExecutionHandler handler: rejection strategy, there are 4 definitions, generally we can customize the rejection strategy
AbortPolicy: RejectedExecutionException is thrown by default to reject the task DiscardPolicy: Abandon the task DiscardOldestPolicy: Throw the oldest task through the queue structure CallerRunsPolicy: The thread that calls the execute method executes the task
1.4 Interview Question Thread Pool Source Code Analysis Execution Schematic (TODO)
1.5 The difference between submit() and execute methods in interview questions (TODO)
The difference between submit and execute: There is a concept of submission priority and execution priority in the thread, and the submission priority is higher than the execution priority. 1. The execute method is in the submit method. 2. The submit method will return a Future generic function, but execute will not return
1.6 The difference between offer() and add() in interview questions
Both add and offer are methods for adding tasks to the task queue. The difference is that the add method does not throw an exception, while the offer will throw an interrupt exception. This is the only difference between them.
1.7 newScheduledThreadPool(TODO)
1.7.1 newScheduledThreadPool combat (TODO)
1.7.2 Source code analysis (TODO)
1.8 Custom Deny Policy
There are two ways to customize the rejection policy:
//Custom rejection strategy RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() { @Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { System.out.println("Custom rejection strategy, can be stored in database"); } } ;The second method: implement the RejectedExecutionHandler interface and rewrite the rejectedExecution method.
import java.util.concurrent.*;
/**
* 第31个任务会拒绝任务
*/
public class ThreadDemo {
public static void main(String[] args) {
//自定义拒绝策略
RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println("自定义拒绝策略,可以存入数据库");
}
};
//定义ThreadPoolExecutor
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 30, 0, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(10),rejectedExecutionHandler);
//定义100个任务给线程池处理对比处理性能
long begin = System.currentTimeMillis();
for(int i=0;i<100;i++){
threadPoolExecutor.submit(new Task());
}
threadPoolExecutor.shutdown();
long end = System.currentTimeMillis();
System.out.println("处理时间:"+(end-begin)/1000+"秒");
}
}
class Task implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"处理完任务");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}