Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java并发编程——四种线程池的使用及分析

Java并发编程——四种线程池的使用及分析

作者头像
向着百万年薪努力的小赵
发布于 2022-12-02 01:37:49
发布于 2022-12-02 01:37:49
39300
代码可运行
举报
文章被收录于专栏:小赵的Java学习小赵的Java学习
运行总次数:0
代码可运行

执行一个异步任务你还只是new Thread吗? 那你就out太多了,new Thread的弊端如下:

a. 每次new Thread新建对象性能差。

b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。

c.缺乏更多功能,如定时执行、定期执行、线程中断。

用线程池吧,少年

相比new Thread,Java提供的四种线程池的好处

a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。

b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

c. 提供定时执行、定期执行、单线程、并发数控制等功能。

Java提供的四种线程池

  1. newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
  2. newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
  3. newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
  4. newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。

了解之后,就让我们来使用一下 代码示例:

1.newFixedThreadPool

创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}

因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。 定长线程池的大小最好根据系统资源进行设置。如Runtime.getRuntime().availableProcessors()。可参考PreloadDataCache。

2.newSingleThreadExecutor

创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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();
}
}
});
}

结果依次输出,相当于顺序执行各个任务。

3.newCachedThreadPool

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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);
}
});
}

线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。

4.newScheduledThreadPool

创建一个定长线程池,支持定时及周期性任务执行。 延迟执行示例代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {

@Override
public void run() {
System.out.println("delay 3 seconds");
}
}, 3, TimeUnit.SECONDS);

表示延迟3秒执行。

定期执行示例代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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秒执行一次。

分析

那光会使用怎么能行,我们还要进去看看它的原理: 点进去创建固定线程池的方法,

原来是调了一个方法,把线程数量当参数传了进去 换一个看看,再点进去缓存线程池

又调用了这个方法,看来ThreadPoolExecutor()这个方法才是创建线程池的真正的方法,让我们再点进去这个方法 打开Structure,看到这个方法有四个重载,传递的不同参数

这里给出参数是什么意思,供大家参考

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public ThreadPoo1Executor(
int corePool size,//核心线程数量
int maximumPoolsize,/最大线程数
long keepAliveTime,//超时时间,超出核心线程数量以外的线程空余存活时间
Timeunit unit,//存活时间单位
BlockingQueue<Runnable> workQueue,//保存执行任务的队列
ThreadFactory threadFactory,//创建新线程使用的工厂
RejectedExecutionHandler handler//当任务无法执行的时候的处理方式
)

这里大家注意一下这两个参数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int corePool size,//核心线程数量
int maximumPoolsize,/最大线程数

其实这就是有编制的和临时工的区别,什么意思呢 就是如果我们公司某个项目赶得紧,人手不够了,怎么办?扩招吗,可是平时又用不到这么多人,那我们可以找外包公司招点外包人员嘛,临时借过来等项目完成了再还回去。 即核心到最大 之间的这部分,是可变的,需要就有,不需要就没有。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-09-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java四种线程池的使用
Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。 newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
Java架构师历程
2018/09/26
4600
Java四种线程池的使用
(十四)Java并发-线程池
(1). newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。示例代码如下:
用户1212940
2022/04/13
2640
Java四种线程池
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
互扯程序
2019/05/09
7430
Java 四种线程池的使用
介绍new Thread的弊端及Java四种线程池的使用 1,线程池的作用 线程池作用就是限制系统中执行线程的数量。 根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果。 少了浪费了
程序员鹏磊
2018/02/09
9970
java创建线程池的四种方式_线程池对象的创建方式
newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
全栈程序员站长
2022/11/10
5150
Executor的介绍及线程池的应用
Executors少了一个创建线程池的方法newScheduledThreadPool()
余生大大
2022/11/02
2690
Executor的介绍及线程池的应用
线程池
线程池的作用: 线程池作用就是限制系统中执行线程的数量。      根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。 为什么要用线程池: 1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行
汤高
2018/01/11
1K0
Java 六种线程池介绍
(1)newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。 可能导致内存溢出,一般使用newFixedThreadPool代替
Jensen_97
2023/07/20
3290
Java中常用的四种线程池
在Java中使用线程池,可以用ThreadPoolExecutor的构造函数直接创建出线程池实例,如何使用参见之前的文章Java线程池构造参数详解。不过,在Executors类中,为我们提供了常用线程池的创建方法。接下来我们就来了解常用的四种:
万猫学社
2022/04/22
8080
java线程池模型
一, 线程池与普通线程 1 普通线程 Java实现多线程,常见的有以下三种方式: 1 继承Thread,重写该类的run()方法 2 实现Runnable 实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象。 3 使用Callable和Future接口创建线程。 具体是创建Callable接口的实现类,并实现clall()方法。并使用
Spark学习技巧
2018/01/31
1.5K0
java线程池模型
016.多线程-线程池的四种创建方式
版权声明:本文为博主原创文章,允许转载,请标明出处。 https://blog.csdn.net/qwdafedv/article/details/84256291
qubianzhong
2018/12/14
1.3K0
016.多线程-线程池的四种创建方式
Java多线程:还不懂线程池吗?一文带你彻底搞懂!
总体来说,线程池有如下的优势: (1)降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 (2)提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。 (3)提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
Java小朔哥
2019/08/13
6510
线程池介绍及创建线程池的4种方式是什么_程序可以创建几个线程池
Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序 都可以使用线程池。在开发过程中,合理地使用线程池能够带来3个好处。 第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。 第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。 第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源, 还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。但是,要做到合理利用 线程池,必须对其实现原理了如指掌。
全栈程序员站长
2022/11/10
5420
线程池介绍及创建线程池的4种方式是什么_程序可以创建几个线程池
JDK1.8 创建线程池有哪几种方式?
定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程
猫头虎
2024/04/07
1560
线程池如何创建线程_创建线程池的七个参数
Executors 类是从 JDK 1.5 开始就新增的线程池创建的静态工厂类,它就是创建线程池的,但是很多的大厂已经不建议使用该类去创建线程池。原因在于,该类创建的很多线程池的内部使用了无界任务队列,在并发量很大的情况下会导致 JVM 抛出 OutOfMemoryError,直接让 JVM 崩溃,影响严重。
全栈程序员站长
2022/11/10
1.2K0
线程池:治理线程的法宝
在当今计算机的CPU计算速度非常快的情况下,为了能够充分利用CPU性能提高程序运行效率我们在程序中使用了线程。但是在高并发情况下会频繁的创建和销毁线程,这样就变相的阻碍了程序的执行速度,所以为了管理线程资源和减少线程创建以及销毁的性能消耗就引入了线程池。
用户1516716
2020/02/20
8340
线程池:治理线程的法宝
线程池的7种创建方式,强烈推荐你用它...
根据摩尔定律所说:集成电路上可容纳的晶体管数量每 18 个月翻一番,因此 CPU 上的晶体管数量会越来越多。
磊哥
2020/12/21
5900
线程池的7种创建方式,强烈推荐你用它...
1.11 手把手教你从多线程到线程池
单CPU系统中: 每一时刻只能有一道程序执行,即微观上这些程序是分时的交替运行,只不过是给人的感觉是同时运行,那是因为分时交替运行的时间是非常短的。 多CPU系统中: 则这些可以并发执行的程序便可以分配到多个处理器上(CPU),实现多任务并行执行,即利用每个处理器来处理一个可以并发执行的程序。
ha_lydms
2023/08/09
2540
1.11 手把手教你从多线程到线程池
(五)四种线程池底层详解
可以看到corePoolSize、maximumPoolSize都是 1 ,keepAliveTime 是 0 ,使用的是LinkedBlockingQueue队列。
HaC
2020/12/30
5300
jdk提供的线程池_创建线程的三种方法
定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化,当线程发生错误结束时,线程池会补充一个新的线程
全栈程序员站长
2022/11/10
2580
相关推荐
Java四种线程池的使用
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验