8.线程池
线程池
池化技术
程序的运行,本质:占用系统的资源,优化资源的使用
线程池,连接池,内存池,对象池,常量池
线程池好处:
- 降低资源消耗
- 提高响应速度
- 方便管理
线程复用,可以控制最大并发数,管理线程
线程池:三大方法
在《阿里巴巴java开发手册》中指出了线程资源必须通过线程池提供,不允许在应用中自行显示的创建线程,这样一方面是线程的创建更加规范,可以合理控制开辟线程的数量;另一方面线程的细节管理交给线程池处理,优化了资源的开销。而线程池不允许使用Executors去创建,而要通过ThreadPoolExecutor方式,这一方面是由于jdk中Executor框架虽然提供了如newFixedThreadPool()、newSingleThreadExecutor()、newCachedThreadPool()等创建线程池的方法,但都有其局限性,不够灵活;另外由于前面几种方法内部也是通过ThreadPoolExecutor方式实现,使用ThreadPoolExecutor有助于大家明确线程池的运行规则,创建符合自己的业务场景需要的线程池,避免资源耗尽的风险。
//Executors 工具类 三大方法
public class Demo01 {
public static void main(String[] args) {
//ExecutorService threadPool = Executors.newSingleThreadExecutor();//单个线程
//ExecutorService threadPool =Executors.newFixedThreadPool(3);//固定数量线程池
ExecutorService threadPool =Executors.newCachedThreadPool();//可伸缩,遇强则强,遇弱则弱
try {
for (int i = 1; i <= 10; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPool.shutdown();
}
}
}
7大参数
源码分析
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
//本质:ThreadPoolExecutor
public ThreadPoolExecutor(int corePoolSize,//核心线程池大小
int maximumPoolSize,//最大线程池大小
long keepAliveTime,//超时了 没人调用就会释放
TimeUnit unit,//超时单位
BlockingQueue<Runnable> workQueue,//阻塞队列,
当请求的线程数大于 corePoolSize时,线程进入该阻塞队列
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;
}
自定义线程池
拒绝策略
1.AbortPolicy() 满了,抛出异常
2.CallerRunsPolicy 哪来的那里去
3.DiscardOldestPolicy 满了,尝试和最早的任务竞争,竞争失败也不会抛出异常
4.DiscardPolicy 满了,丢掉任务,不会抛出异常
//自定义线程池
/*
拒绝策略
1.AbortPolicy() 满了,抛出异常
2.CallerRunsPolicy 哪来的那里去
3.DiscardOldestPolicy 满了,尝试和最早的任务竞争,竞争失败也不会抛出异常
4.DiscardPolicy 满了,丢掉任务,不会抛出异常
*
* */
public class Demo02 {
public static void main(String[] args) {
/*最大线程数如何定义
* 1.CPU密集型 几核就是几,可以保持CPU效率最高
*2.IO 密集型 判断你程序中十分耗IO的线程,最大线程数=IO*2
* 程序中有15个大型任务,最大线程15*2=30
* */
//获取cpu核数
int cpu = Runtime.getRuntime().availableProcessors();
System.out.println(cpu);
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
2,
5,
3, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()//银行满了,还有人进来,不处理这个人的,抛出异常
);
try {
//最大8个=队列+max=3+5
//超过8,抛出异常RejectedExecutionException,由拒绝策略决定
for (int i = 1; i <= 9; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
拓展
最大线程数如何定义
-
CPU密集型 几核就是几,可以保持CPU效率最高
-
IO 密集型 判断你程序中十分耗IO的线程,最大线程数=IO*2
程序中有15个大型任务,最大线程15*2=30
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY