Java常用线程池的用法分析
在Java中,java.util.concurrent.Executors
工具类提供了四个静态工厂方法来创建不同特性的线程池,它们分别是:
1. FixedThreadPool
ExecutorService newFixedThreadPool(int nThreads)
- 特点:创建一个定长的线程池,包含固定数量的核心线程,且所有线程均是核心线程。当线程池中的线程都在运行时,新提交的任务将会进入无界的工作队列中等待执行。如果线程池中的某个线程由于异常结束,那么线程池会再新建一个线程来替代。此线程池保证任何时候池中线程数不超过设定值,适用于处理大量短生命周期的任务,能有效控制系统资源。
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。
定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。可参考PreloadDataCache。
2. CachedThreadPool
ExecutorService newCachedThreadPool()
- 特点:创建一个可缓存的线程池,线程池根据需要自动创建或销毁线程。如果线程池中的线程数量超过了处理任务所需要的线程数量,那么多余的空闲线程将在一段时间后被终止并回收;当需要执行新的任务时,如果线程池中有空闲线程则复用,如果没有则创建新线程。这意味着此类线程池大小几乎没有限制,适合处理大量短耗时且突发性强的任务,但可能导致线程数量过多,需要注意系统的资源限制。
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
try {
Thread.sleep(index * 1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(index);
}
});
}
线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
3. SingleThreadExecutor
ExecutorService newSingleThreadExecutor()
- 特点:创建一个只有一个工作线程的线程池,所有提交的任务在这个线程中按照先入先出的顺序执行。实际上,这是一个特殊的固定线程池,保证同一时间只有一个任务被执行,常用于需要串行执行任务的场景。
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
try {
System.out.println(index);
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
结果依次输出,相当于顺序执行各个任务。
现行大多数GUI程序都是单线程的。Android中单线程可用于数据库操作,文件操作,应用批量安装,应用批量删除等不适合并发但可能IO阻塞性及影响UI线程响应的操作。
4. ScheduledThreadPool
ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
- 特点:创建一个定长的线程池,支持定时及周期性任务执行。它允许延时或者定期地执行任务,并且能够调度多个定时任务。相比FixedThreadPool,ScheduledThreadPool多了定时任务的功能,线程池内的线程数也可以动态调整,但核心线程不会被回收。
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);
表示延迟3秒执行。
定期执行示例代码如下:
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("delay 1 seconds, and excute every 3 seconds");
}
}, 1, 3, TimeUnit.SECONDS);
表示延迟1秒后每3秒执行一次。
ScheduledExecutorService比Timer更安全,功能更强大
5. ThreadPoolTaskExecutor (Spring框架)
ThreadPoolTaskExecutor
是Spring框架对Java原生线程池API进行封装后的组件,它基于java.util.concurrent.ThreadPoolExecutor
,并添加了一些Spring特有的功能特性,使得在Spring应用中使用线程池更为方便和灵活。
ThreadPoolTaskExecutor的主要特点和配置项包括:
- 核心线程数(corePoolSize):线程池的基本大小。
- 最大线程数(maxPoolSize):线程池所能容纳的最大线程数。
- 空闲线程存活时间(keepAliveSeconds):超过核心线程数的线程,在空闲多久后会被终止。
- 队列容量(queueCapacity):阻塞队列的大小,当线程池中所有线程都忙碌时,新提交的任务将放入队列等待执行。
- 线程前缀名称(threadNamePrefix):设置线程的命名前缀,方便识别和调试。
- 线程工厂(threadFactory):可以自定义线程创建规则。
- 拒绝策略(RejectedExecutionHandler):当队列和线程池都无法接受新任务时,定义如何处理被拒绝的任务。
使用ThreadPoolTaskExecutor
可以在Spring配置文件中通过bean的方式进行配置,然后在代码中注入该bean来执行异步任务,这样可以更好地与Spring容器整合,实现任务的异步处理和调度。例如:
log.info("线程执行");
//多线程异步执行
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(1);
executor.setMaxPoolSize(5);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("createUserNoticeLog-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
ThreadPoolExecutor pushExecutorService = executor.getThreadPoolExecutor();
pushExecutorService.submit(() -> {
//相关程序逻辑 ,比如发送用户短信
sms.sned("15011462646","msg text")
log.info("批量发送短信线程执行");
});
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!