一、 线程池种类:
1、newFixedThreadPool:
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
* {@code nThreads} threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
* prior to shutdown, a new one will take its place if needed to
* execute subsequent tasks. The threads in the pool will exist
* until it is explicitly {@link ExecutorService#shutdown shutdown}.
*
* @param nThreads the number of threads in the pool
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue, using the provided
* ThreadFactory to create new threads when needed. At any point,
* at most {@code nThreads} threads will be active processing
* tasks. If additional tasks are submitted when all threads are
* active, they will wait in the queue until a thread is
* available. If any thread terminates due to a failure during
* execution prior to shutdown, a new one will take its place if
* needed to execute subsequent tasks. The threads in the pool will
* exist until it is explicitly {@link ExecutorService#shutdown
* shutdown}.
*
* @param nThreads the number of threads in the pool
* @param threadFactory the factory to use when creating new threads
* @return the newly created thread pool
* @throws NullPointerException if threadFactory is null
* @throws IllegalArgumentException if {@code nThreads <= 0}
*/
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
创建一个可重用的固定线程数的线程池,以共享无边界的方式运行这些线程。在任意时刻,大多数nThread线程会处于处理任务的状态。如果在所有线程处于活动状态
时提交附加的任务,则在可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间,由于失败而导致任何线程终止,则一个新线程将代替它执行后续的任务(如果需要)。
如果在某个线程被显式的关闭之前,池中的线程将会一直存在。
特征:
- 1、线程池中的线程处于一定的数量,可以很好的控制线程的并发数;
- 2、线程可以被重复使用,显式关闭之前,一直存在;
- 3、超出一定数量的线程被提交时,需在队列中等待。
测试代码:
public class ThreadPoolExecutorTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolExecutorTest.class);
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@SneakyThrows
@Override
public void run() {
LOGGER.info("newFixedThreadPool测试");
Thread.sleep(10);
}
});
}
}
}
测试结果:
10:11:42.566 [pool-1-thread-1] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newFixedThreadPool测试
10:11:42.566 [pool-1-thread-2] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newFixedThreadPool测试
10:11:42.566 [pool-1-thread-3] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newFixedThreadPool测试
10:11:42.566 [pool-1-thread-4] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newFixedThreadPool测试
10:11:42.566 [pool-1-thread-5] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newFixedThreadPool测试
10:11:42.580 [pool-1-thread-1] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newFixedThreadPool测试
10:11:42.581 [pool-1-thread-2] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newFixedThreadPool测试
10:11:42.581 [pool-1-thread-3] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newFixedThreadPool测试
10:11:42.581 [pool-1-thread-4] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newFixedThreadPool测试
10:11:42.581 [pool-1-thread-5] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newFixedThreadPool测试
2、newWorkStealingPool:
/**
* Creates a work-stealing thread pool using all
* {@link Runtime#availableProcessors available processors}
* as its target parallelism level.
* @return the newly created thread pool
* @see #newWorkStealingPool(int)
* @since 1.8
*/
public static ExecutorService newWorkStealingPool() {
return new ForkJoinPool
(Runtime.getRuntime().availableProcessors(),
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
/**
* Creates a thread pool that maintains enough threads to support
* the given parallelism level, and may use multiple queues to
* reduce contention. The parallelism level corresponds to the
* maximum number of threads actively engaged in, or available to
* engage in, task processing. The actual number of threads may
* grow and shrink dynamically. A work-stealing pool makes no
* guarantees about the order in which submitted tasks are
* executed.
*
* @param parallelism the targeted parallelism level
* @return the newly created thread pool
* @throws IllegalArgumentException if {@code parallelism <= 0}
* @since 1.8
*/
public static ExecutorService newWorkStealingPool(int parallelism) {
return new ForkJoinPool
(parallelism,
ForkJoinPool.defaultForkJoinWorkerThreadFactory,
null, true);
}
特征:
创建持有足够数量线程的线程池,来支持给定的并行级别,该方法还有使用多个队列来减少竞争。
3、newSingleThreadExecutor:
/**
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue. (Note however that if this single
* thread terminates due to a failure during execution prior to
* shutdown, a new one will take its place if needed to execute
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
* {@code newFixedThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
*
* @return the newly created single-threaded Executor
*/
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
/**
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue, and uses the provided ThreadFactory to
* create a new thread when needed. Unlike the otherwise
* equivalent {@code newFixedThreadPool(1, threadFactory)} the
* returned executor is guaranteed not to be reconfigurable to use
* additional threads.
*
* @param threadFactory the factory to use when creating new
* threads
*
* @return the newly created single-threaded Executor
* @throws NullPointerException if threadFactory is null
*/
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
作用:
创建一个使用单个worker线程的Executor,以无界队列方式来运行该线程(如果因为在关闭之前的执行期间因为失败而终止了此单个线程,那么如果需要,一个新线程将
代替他执行后续的任务)。可以保证顺序地执行各个任务,并且在任意给定的时间,不会有多个线程时活动的。
与其他等效的newFixedThreadPool(1)不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。//TODO:?
特征:
1、线程池中最多执行一个线程,之后提交的线程将会在队列中等待执行,且线程的存活时间时无限制的。
测试代码:
public class ThreadPoolExecutorTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolExecutorTest.class);
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@SneakyThrows
@Override
public void run() {
System.out.println("测试" + Thread.currentThread().getName());
Thread.sleep(10);
}
});
}
}
}
测试结果:
测试pool-1-thread-1
测试pool-1-thread-1
测试pool-1-thread-1
测试pool-1-thread-1
测试pool-1-thread-1
测试pool-1-thread-1
测试pool-1-thread-1
测试pool-1-thread-1
测试pool-1-thread-1
测试pool-1-thread-1
4、newCachedThreadPool:
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
* Calls to {@code execute} will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
* the cache. Thus, a pool that remains idle for long enough will
* not consume any resources. Note that pools with similar
* properties but different details (for example, timeout parameters)
* may be created using {@link ThreadPoolExecutor} constructors.
*
* @return the newly created thread pool
*/
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
/**
* Creates a thread pool that creates new threads as needed, but
* will reuse previously constructed threads when they are
* available, and uses the provided
* ThreadFactory to create new threads when needed.
* @param threadFactory the factory to use when creating new threads
* @return the newly created thread pool
* @throws NullPointerException if threadFactory is null
*/
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
作用:
创建一个可根据需要创建新线程的线程池,但是在之前构造的线程可用时可进行复用,并在需要时使用提供的ThreadFactory创建新线程。
特征:
- 1、线程池中线程数没有固定数量,可达到的最大值为(Integer.MAX_VALUE);
- 2、线程池中的线程可进行缓存重复利用和回收(回收默认时间为60s);
Note:
SynchronousQueue同步队列,因此会在线程池中寻找可用线程来执行,若有可用线程则执行,没有可用线程则创建一个新线程执行。池中的线程空闲时间超过60s,
则会被销毁。
使用场景:
适合执行大量小任务的场景。
测试代码:
public class ThreadPoolExecutorTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolExecutorTest.class);
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@SneakyThrows
@Override
public void run() {
LOGGER.info("newCachedThreadPool测试");
Thread.sleep(100);
}
});
}
}
}
测试结果:
10:22:57.532 [pool-1-thread-1] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newCachedThreadPool测试
10:22:57.532 [pool-1-thread-4] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newCachedThreadPool测试
10:22:57.534 [pool-1-thread-5] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newCachedThreadPool测试
10:22:57.530 [pool-1-thread-2] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newCachedThreadPool测试
10:22:57.530 [pool-1-thread-3] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newCachedThreadPool测试
10:22:57.534 [pool-1-thread-6] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newCachedThreadPool测试
10:22:57.534 [pool-1-thread-7] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newCachedThreadPool测试
10:22:57.535 [pool-1-thread-8] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newCachedThreadPool测试
10:22:57.535 [pool-1-thread-9] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newCachedThreadPool测试
10:22:57.535 [pool-1-thread-10] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - newCachedThreadPool测试
5、newScheduledThreadPool
/**
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
/**
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
* even if they are idle
* @param threadFactory the factory to use when the executor
* creates a new thread
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
* @throws NullPointerException if threadFactory is null
*/
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
创建一个线程池,它可以给定安排延迟后执行命令或者周期地执行。
特征:
- 1、线程池中保留一定数量的线程,即使空闲也将保留;
- 2、可以定时或者延迟执行线程活动。
测试代码:
public class ThreadPoolExecutorTest {
private static final Logger LOGGER = LoggerFactory.getLogger(ThreadPoolExecutorTest.class);
public static void main(String[] args) {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 10; i++) {
executorService.schedule(new Runnable() {
@SneakyThrows
@Override
public void run() {
LOGGER.info("延迟线程池测试");
Thread.sleep(10);
}
}, 1, TimeUnit.SECONDS);
}
}
}
测试结果:
10:08:15.333 [pool-1-thread-1] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - 延迟线程池测试
10:08:15.333 [pool-1-thread-2] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - 延迟线程池测试
10:08:15.334 [pool-1-thread-3] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - 延迟线程池测试
10:08:15.334 [pool-1-thread-4] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - 延迟线程池测试
10:08:15.333 [pool-1-thread-5] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - 延迟线程池测试
10:08:15.347 [pool-1-thread-5] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - 延迟线程池测试
10:08:15.347 [pool-1-thread-3] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - 延迟线程池测试
10:08:15.347 [pool-1-thread-4] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - 延迟线程池测试
10:08:15.347 [pool-1-thread-1] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - 延迟线程池测试
10:08:15.347 [pool-1-thread-2] INFO com.zjft.zhyg.common.config.ThreadPoolExecutorTest - 延迟线程池测试
二、ThreadPoolExecutor 线程池参数:
/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @param threadFactory the factory to use when the executor
* creates a new thread
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue}
* or {@code threadFactory} or {@code handler} is null
*/
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;
}
- corePoolSize: 线程池核心线程大小
线程池中会维护一个最小的线程数量,即使这些线程处于空闲状态也不会被销毁,除非设置了allowCoreThreadTimeOut。最小线程数即为corePoolSize。
- maximumPoolSize: 线程池最大线程数量
一个线程被提交到线程池以后,首先会找有没有空闲存活线程,如果有则直接把任务交给这个空闲线程来执行,如果没有则会缓存到队列中,如果队列满了,才会创建一个新线程,然后从工作队列的头部取出一个任务交由新线程来处理,而将刚提交的任务放入队列尾部。线程池不会无限制的创建线程,它有一个最大的数量限制,即为maximumPoolSize。
- keepAliveTime: 线程空闲存活时间
- unit: 时间单位
- workQueue: 任务队列,被提交但尚未执行的任务
阻塞队列,用于存储等待执行的任务,阻塞队列有以下几种选择:
ArrayBlockingQueue:
基于数组的有界阻塞队列,按FIFO排序。新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题,当线程池中的线程数量达到corePoolSize时,
再有新任务进来,则会将任务放入该队列的队尾,等待被调度。如果队列已满,则创建一个新线程,如果线程数量已经达到maximumPoolSize,则会执行拒绝策略。LinkedBlockingQueue:
基于链表的无界队列(其实最大容量为Integer.MAX_VALUE),按照FIFO排序。由于该队列的近似无界性,当线程池中线程数量达到corePoolSize时,再有新任
务进来,就会存入该队列,而不会创建新线程直到达到线程数量达到maximumPoolSize,因此使用该队列时,参数maximumPoolSize是不起作用的。SynchronousQueue:
一个不缓存任务的队列,生产者放入一个任务必须要等到消费者取出这个任务,也就是说新任务不会被缓存,而是直接被调度执行这个任务,如果没有可用线程,则
创建新线程,如果线程数量达到maximumPoolSize,则执行拒绝策略。PriorityBlockingQueue:
具有优先级的无界阻塞队列,优先级通过参数Comparator实现。
- threadFactory: 线程工厂
线程池中生成线程的工厂,用于创建线程,一般为默认线程工厂即可。
- handler: 拒绝策略
当线程池的线程已经达到线程池能够创建的最大线程数且阻塞队列也已经满了的时候,还有线程想要被创建执行,就会执行拒绝策略。
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常;
ThreadPoolExecutor.DiscardPolicy:
丢弃任务但是不抛出异常;
ThreadPoolExecutor.DiscardOldestPolicy:
丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程);
ThreadPoolExecutor.CallerRunsPolicy:
由调用线程处理该任务;
如何配置线程池的各个参数:
- CPU密集型任务:
尽量使用较小的线程池,一般为CPU核心数+1。因为CPU密集型任务使得CPU使用率高,若开过多的线程,会使得CPU增加上下文切换的次数,增加额外的开销。 - IO密集型任务:
可以使用较大的线程数,一般为2*CPU核心数 + 1,因为IO操作不占用CPU资源,为了合理利用CPU资源,应加大线程数量,这样可以在CPU在等待IO的时候去处理
别的任务,充分利用CPU的时间。