网站首页 > java教程 正文
线程池化技术,是通过一个公用的线程队列,将一个或多个线程进行统一资源调用,可以支持线程资源的重复使用的技术,可以有效的避免因为线程调用创建和销毁线程过程带来的资源消耗问题。
为什么要使用线程池?
1、可以通过重复利用创建好的线程来降低线程创建和销毁造成的资源消耗
2、可以提升系统响应速度,因为核心线程是一直存在的,所以多线程任务不需要等待线程创建就可以立即执行任务。
3、可以利用线程池对线程资源进行统一的管理,避免线程创建过多导致的内存溢出问题等问题。
Java中如何来实现线程池的管理的?
Java是从JDK1.5开始的时候,将工作单元与线程执行机制进行了分离来提供线程池的使用管理机制,其中工作单元主要就是包括Runnable和Callable,而线程的执行机制则是交给了Executors来提供,代码如下。
首先我们来创建一个用于测试的线程类。
public class TestThread implements Runnable {
private String count;
public TestThread(String count) {
this.count = count;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" 开始计数 Count = "+count);
executeCount();
System.out.println(Thread.currentThread().getName()+" 结束计数");
}
private void executeCount() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString(){
return this.count;
}
}
创建测试主类
public class SimpleTheadPool {
public static void main(String[] args) {
// 创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(5);
//创建执行线程操作
for (int i = 0; i < 10; i++) {
Runnable testThread = new TestThread(String.valueOf(i));
executorService.execute(testThread);
}
executorService.shutdown();
while (executorService.isTerminated()){
}
System.out.println("完成所有线程");
}
}
在测试类中,创建了一个固定大小的线程池,并且给线程池分配了10个需要执行的测试任务,因为线程池的初始大小是5,所以无法一次容纳10个线程的处理,所以当线程进入之后,会有一部分线程进入到等待状态,当前面进入的线程执行完成之后,后续的线程就会自动进入执行,执行效果如下图所示。
从执行结果来看,线程池中只存在了五个线程,并且这五个线程并不会随着工作执行完成而销毁,会一直等待分配线程执行任务,一直到线程池调用了销毁函数来进行销毁。
Executors使用了ExecutorService提供的线程实现,并且newFixedThreadPool() 方法创建了如下的一个线程池类。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
下面我们就来看看ThreadPoolExecutor线程池类
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
// 省略代码
}
corePoolSize:核心线程数,当我们往线程池中添加一个任务之后,线程池会创建一个新的线程去执行任务,当创建的线程数等于corePoolSize之后。继续提交任务就会被阻塞到队列中,等待执行。当然如果调用了prestartAllCoreThreads()方法,线程池也会启动所有的核心线程。
workQueue:用来保存等待执行任务的阻塞队列。
maximumPoolSize:线程池中被允许的最大线程数。当等待执行阻塞队列装满之后,如果继续提交任务,则会继续创建线程去执行任务,前提是创建的线程数要小于maximumPoolSize值。这里需要注意的是如果队列可以存放的任务是无限的,那么这个参数就不会起作用,因为队列会一直存放等待线程。
keepAliveTime:线程空闲等待时间,当线程没有需要执行的任务的时候,就会在等待指定时间之后被销毁,默认情况下只会销毁超过corePoolSize数的线程。
unit:设置等待的线程时间单位
threadFactory: 创建线程的工厂类。通过自定义的方式可以给每个线程创建一个具有识别性的线程名称,用于后续问题定位。
handler: 线程拒绝策略,当队列满的时候,如果没有空闲线程执行任务,那么就需要拒绝策略的参与。
实现方式
newFixedThreadPool
当线程数达到了核心线程数之后,即使没有可以执行的任务,线程池也不会释放线程。并且这个线程池采用了一个无界的队列,也就是说阻塞队列永远不会达到饱和。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
newSingleThreadExecutor
初始化线程池中只有一个线程执行任务,如果这个线程因为异常而结束工作,则会重新创建一个新的线程来继续执行该任务,这个唯一线程的执行操作就可以保证所有的提交任务都是按照队列排序顺序执行。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
newCachedThreadPool
这线程池的线程数可以达到Integer.MAX_VALUE值,并且内部使用了SynchronousQueue队列来作为阻塞队列。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
总结
上面我们介绍了在Java中如何去创建一个线程池,并且介绍了创建线程池相关的核心参数。在后续的分享中还会给大家详细介绍关于Java中线程池的使用,敬请期待
- 上一篇: Java的线程池是怎么回事?来看看这篇文章吧
- 下一篇: java线程池创建方式
猜你喜欢
- 2024-11-23 不清楚Java线程池实现原理?那你应该收藏这篇文章!「源码分析」
- 2024-11-23 Java基础——Java多线程(线程的创建方式)
- 2024-11-23 「一文搞懂」Java线程池实现原理
- 2024-11-23 Java线程池
- 2024-11-23 java线程池实现原理以及应用场景说明
- 2024-11-23 快速弄懂Java线程池
- 2024-11-23 java线程池原理浅析
- 2024-11-23 彻底了解线程池的原理——40行从零开始自己写线程池
- 2024-11-23 Java并发编程(8):Executor框架 - 可扩展线程池WorkStealingPool
- 2024-11-23 java中的线程池
你 发表评论:
欢迎- 最近发表
-
- 五,网络安全IDA Pro反汇编工具初识及逆向工程解密实战
- 「JAVA8」- Lambda 表达式(java lambda表达式原理)
- 深入探讨Java代码保护:虚拟机保护技术的新时代
- Nginx反向代理原理详解(图文全面总结)
- 逆向拆解日本IT,哪些Java技术栈薪资溢价高
- mybatis 逆向工程使用姿势不对,把表清空了,心里慌的一比
- Spring Boot集成ProGuard轻松实现Java 代码混淆, Java 应用固若金汤
- 从 Java 代码逆向工程生成 UML 类图和序列图
- 人与人相处:尊重是标配,靠谱是高配,厚道是顶配
- Windows系统安装日期如何修改(windows10怎么修改安装日期)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)