java Pooling technology in can be prepared for us before we open up new threads , This reduces the overhead of the system . Thread pool helps us manage threads in a unified way , It also improves the response of the system .jdk concurrent Medium Executors Class gives us a way to create a thread pool , Simple and easy to use . There are mainly the following methods :
- newFixedThreadPool(int nThreads) Thread pool with fixed number of threads ;
- newSingleThreadExecutor() A thread pool that produces only a single thread ;
- newCachedThreadPool Cache type thread pool , The number of threads is scalable , Not fixed ;
Let's start with , In addition to these jdk Give us a packaged method , We can create our own thread pool manually , Self creation can deepen our impression of this part of knowledge , We can do it by calling ThreadPoolExecutor To create :
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
Take a look at his overloaded constructor :
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
In its construction method , There are several important parameters :
- corePoolSize Number of core threads in thread pool ;
- maximumPoolSize The maximum number of threads in the thread pool ;
- keepAliveTime Idle thread inventory time , Beyond this time, it will be recycled ( More than the number of core threads );
- unit Time unit ;
- workQueue Blocking queues , When the number of threads exceeds the number of core threads , The task will be put in the queue ;
- threadFactory Thread factory , Used to create threads , The default inner class is used ,ThreadPoolExecutor There is no setter/getter Method ;
- handler Refusal strategy , When the blocking queue is full , And when the maximum number of threads is exceeded , Will implement the rejection strategy reject Method .
Take a look at the thread of thread execution in thread pool execute Method :
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
// If the number of worker threads is less than the number of core threads , call addWorker Method and return directly to
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// Exceeded the number of core threads , Priority added to blocking queue
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
// The blocking queue is full , New thread ( Every thread is a worker) To add to workers.
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// The blocking queue is full , And the number of threads is greater than the maximum number of threads , call handler Of rejectedExecution Method .
else if (!addWorker(command, false))
reject(command);
}
Let's look at the rejection strategy of the thread pool ,ThreadPoolExecutor, There's a property defaultHandler, The default rejection strategy . The type is AbortPolicy: Its rejectedExecution The method is to throw an exception .
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
DiscardPolicy: Don't do anything? , Give up this mission
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
DiscardOldestPolicy: Abandon the task ahead , Add new tasks to the cache queue :
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
// Pop up the top task
e.getQueue().poll();
// Perform new tasks
e.execute(r);
}
}
CallerRunsPolicy: Executed by the calling thread run Method :
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
// As you can see, only the current thread called run Method , There is no new thread .
r.run();
}
}
Summary :
This paper mainly introduces the creation methods of thread pool 、ThreadPoolExecutor The constructor and the meaning of the seven parameters , At the same time, it also expounds the function and principle of four rejection strategies .