java线程池优点:
-
降低线程创建和销毁的开销,提高系统性能。
-
提高线程的利用率和系统的吞吐量。
-
统一线程的管理和监控,避免线程泄漏和线程安全问题。
-
支持任务队列和拒绝策略等机制,提供灵活的任务调度和任务处理能力。
并不是所有的业务场景都需要线程池,因为线程池中会涉及到调度相关的内容,如果业务量非常少,并且应用了线程池,可能会导致性能降低。
一、ThreadPoolExecutor线程池实例构造函数如下:
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.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
corePoolSize:核心线程数,提交任务后首先通过核心线程执行任务,当核心线程数达到corePoolSize值的时候,会开辟新的线程执行任务。一般来说核心线程数设置的值为CPU核数,具体情况根据具体的业务来分析。
maximumPoolSize:最大线程数,包括核心线程和非核心线程。
keepAliveTime:非核心线程存活时间,当核心线程数能够执行当前任务时,非核心线程处于空闲状态,但是并不会立马消失,如果设置存活时间,则会等存活时间过之后会被回收。
unit:keepAliveTime的单位,主要包括DAYS:时间单位代表二十四小时;HOURS:时间单位代表六十分钟;MICROSECONDS:时间单位代表千分之一毫秒;MILLISECONDS:时间单位为千分之一秒;MINUTES:时间单位代表6o秒;NANOSECONDS:时间单位代表千分之一千分之一;SECONDS:时间单位代表一秒。
workQueue:存储等待执行任务的队列。
threadFactory:线程工厂,用于创建线程。
handler:拒绝策略,主要包含以下几种。
1、默认的策略:直接抛出异常
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
2、直接由提交任务的线程执行任务,不用去到队列中
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
/**
* Executes task r in the caller's thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
// 直接通过r来执行任务
r.run();
}
}
}
3、丢弃掉阻塞队列中最靠前的任务
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
/**
* Obtains and ignores the next task that the executor
* would otherwise execute, if one is immediately available,
* and then retries execution of task r, unless the executor
* is shut down, in which case task r is instead discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
// 返回队里中的头部元素
e.getQueue().poll();
e.execute(r);
}
}
}
4、丢弃掉当前任务
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
二、线程池的相关状态
RUNNING:线程池运行状态,可以接收新的任务,并且可以处理阻塞队列中的任务。
SHUTDOWN:关闭状态,关闭意味着不会去接收新的任务,但是可以处理阻塞队列中已经存在的任务。
STOP:线程池处于停止状态,不会接收新的任务,同时也不会再执行阻塞队列中已经存在的任务。
TIDYING:所有的任务执行完成或者被终止处于该状态。
TERMINATED:当所有的任务终止或者被执行完毕的时候,所有的线程被清空的时候,线程池会处于该状态。
执行线程的方法:execute(),submit(),shutdown(),shutdownNow()
三、创建线程也可以使用Executors类,可以创建不同的线程池,比如:
-
newFixedThreadPool(int nThreads)
: 创建一个固定大小的线程池。 -
newCachedThreadPool()
: 创建一个可缓存的线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 -
newSingleThreadExecutor()
: 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证按提交顺序执行。 -
newScheduledThreadPool(int corePoolSize)
: 创建一个固定大小的线程池,可以在给定的延迟后执行或定期执行任务。 -
newSingleThreadScheduledExecutor()
: 创建一个单线程化的线程池,可以在给定的延迟后执行或定期执行任务。
通过此方法创建的线程池返回的也是ThreadPoolExecutor对象,只是给定了相关的参数,比如newCachedThreadPool源码如下:
public static ExecutorService newCachedThreadPool() {
// 返回ThreadPoolExecutor对象
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
newScheduledThreadPool线程池可以通过调度的方式进行执行,示例如下:
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
// 可以设置延迟几秒后执行任务
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
log.info("任务执行");
}
},2, TimeUnit.SECONDS);
// 间隔一秒 每三秒执行一次
/**
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
*/
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
log.info("任务执行");
}
},1,3,TimeUnit.SECONDS);