ThreadPoolExecutor之二:jdk实现的线程池介绍
一 简介
线程的使用在java中占有极其重要的地位,在jdk1.4极其之前的jdk版本中,关于线程池的使用是极其简陋的。在jdk1.5之后这一情况有了很大的改观。Jdk1.5之后加入了java.util.concurrent包,这个包中主要介绍java中线程以及线程池的使用。为我们在开发中处理线程的问题提供了非常大的帮助。
二:线程池
线程池的作用:
线程池作用就是限制系统中执行线程的数量。
根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果;少了浪费了系统资源,多了造成系统拥挤效率不高。用线程池控制线程数量,其他线程排队等候。一个任务执行完毕,再从队列的中取最前面的任务开始执行。若队列中没有等待进程,线程池的这一资源处于等待。当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了;否则进入等待队列。
为什么要用线程池:
1.减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
2.可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越大,最后死机)。
Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。
Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
比较重要的几个类:
ExecutorService |
真正的线程池接口。 |
ScheduledExecutorService |
能和Timer/TimerTask类似,解决那些需要任务重复执行的问题。 |
ThreadPoolExecutor |
ExecutorService的默认实现。 |
ScheduledThreadPoolExecutor |
继承ThreadPoolExecutor的ScheduledExecutorService接口实现,周期性任务调度的类实现。 |
要配置一个线程池是比较复杂的,尤其是对于线程池的原理不是很清楚的情况下,很有可能配置的线程池不是较优的,
因此在Executors类里面提供了一些静态工厂,生成一些常用的线程池。有如下几个静态的工厂方法创建线程:
1. newSingleThreadExecutor方法:
public static ExecutorService newSingleThreadExecutor()
创建一个单线程的线程池。这个线程池只有一个线程在工作,也就是相当于单线程串行执行所有任务。如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
默认使用LinkedBlockingQueue队列。
2. newFixedThreadPool方法:
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定大小的线程池。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
默认使用LinkedBlockingQueue队列。
3. newCachedThreadPool方法:
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,
那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。
默认使用SynchronousQueue队列。
4. newScheduledThreadPool方法:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。
默认使用DelayedWorkQueue队列。
实例
1:newSingleThreadExecutor
MyThread.java
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "正在执行。。。");
}
}
TestSingleThreadExecutor.java
public class TestSingleThreadExecutor {
public static void main(String[] args) {
// 创建一个可重用固定线程数的线程池
ExecutorService pool = Executors. newSingleThreadExecutor();
// 创建实现了Runnable口对象,Thread对象当然也实现了Runnable接口
Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
// 将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
// 关闭线程池
pool.shutdown();
}
}
输出结果
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-1正在执行。。。
2 newFixedThreadPool
TestFixedThreadPool.Java
public class TestFixedThreadPool {
public static void main(String[] args) {
// 创建一个可重用固定线程数的线程池
ExecutorService pool = Executors.newFixedThreadPool(2);
// 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
// 将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
// 关闭线程池
pool.shutdown();
}
}
输出结果
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
pool-1-thread-2正在执行。。。
pool-1-thread-1正在执行。。。
3 newCachedThreadPool
TestCachedThreadPool.java
public class TestCachedThreadPool {
public static void main(String[] args) {
// 创建一个可重用固定线程数的线程池
ExecutorService pool = Executors.newCachedThreadPool();
// 创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
Thread t1 = new MyThread();
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
Thread t5 = new MyThread();
// 将线程放入池中进行执行
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.execute(t5);
// 关闭线程池
pool.shutdown();
}
}
输出结果:
pool-1-thread-2正在执行。。。 pool-1-thread-4正在执行。。。 pool-1-thread-3正在执行。。。 pool-1-thread-1正在执行。。。 pool-1-thread-5正在执行。。。 |
4 newScheduledThreadPool
TestScheduledThreadPoolExecutor.java
public class TestScheduledThreadPoolExecutor {
public static void main(String[] args) {
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
exec.scheduleAtFixedRate(new Runnable() {// 每隔一段时间就触发异常
@Override
public void run() {
//throw new RuntimeException();
System.out.println("================");
}
}, 1000, 5000, TimeUnit.MILLISECONDS);
exec.scheduleAtFixedRate(new Runnable() {// 每隔一段时间打印系统时间,证明两者是互不影响的
@Override
public void run() {
System.out.println(System.nanoTime());
}
}, 1000, 2000, TimeUnit.MILLISECONDS);
}
}
输出结果
================ 8384644549516 8386643829034 8388643830710 ================ 8390643851383 8392643879319 8400643939383 |
ThreadPoolExecutor之二:jdk实现的线程池介绍的更多相关文章
- JDK自带线程池介绍及使用环境
1.newFixedThreadPool创建一个指定工作线程数量的线程池.每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中. 2.newCach ...
- 从源码看JDK提供的线程池(ThreadPoolExecutor)
一丶什么是线程池 (1)博主在听到线程池三个字的时候第一个想法就是数据库连接池,回忆一下,我们在学JavaWeb的时候怎么理解数据库连接池的,数据库创建连接和关闭连接是一个比较耗费资源的事情,对于那些 ...
- Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理
相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...
- JDK自带线程池学习
JDK自带线程池 线程池的状态 线程有如下状态 RUNNING状态:Accept new tasks and process queued tasks SHUTDOWN状态:Don't accept ...
- Java提高班(二)深入理解线程池ThreadPool
本文你将获得以下信息: 线程池源码解读 线程池执行流程分析 带返回值的线程池实现 延迟线程池实现 为了方便读者理解,本文会由浅入深,先从线程池的使用开始再延伸到源码解读和源码分析等高级内容,读者可根据 ...
- Java高并发程序设计学习笔记(六):JDK并发包(线程池的基本使用、ForkJoin)
转自:https://blog.csdn.net/dataiyangu/article/details/86573222 1. 线程池的基本使用1.1. 为什么需要线程池1.2. JDK为我们提供了哪 ...
- Java多线程总结(二)锁、线程池
掌握Java中的多线程,必须掌握Java中的各种锁,以及了解Java中线程池的运用.关于Java多线程基础总结可以参考我的这篇博文Java多线程总结(一)多线程基础 转载请注明出处——http://w ...
- Java并发(二十一):线程池实现原理
一.总览 线程池类ThreadPoolExecutor的相关类需要先了解: (图片来自:https://javadoop.com/post/java-thread-pool#%E6%80%BB%E8% ...
- Java多线程和并发(十二),Java线程池
目录 1.利用Executors创建线程的五种不同方式 2.为什么要使用线程池 3.Executor的框架 4.J.U.C的三个Executor接口 5.ThreadPoolExecutor 6.线程 ...
随机推荐
- 2019年北航OO第3单元(JML)总结
1 JML语言的理论基础及应用工具链 1.1 JML语言 Java建模语言(JML)是一种行为接口规范语言,可用于指定Java模块的行为.它结合了Eiffel的"契约设计(design by ...
- BZOJ3786 星际探索
@(BZOJ)[DFS序, Splay] Description 物理学家小C的研究正遇到某个瓶颈. 他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其 ...
- 【kotlin】基本语法when的使用,类似于java中的switch,但是又青出于蓝而胜于蓝
when(要判断的参数){ 参数值为1 ->做这种事情 参数值为2 ->做另一种事情 else -> 类似于switch中的default } 扩展使用:https://www.cn ...
- Mysql 性能优化20个原则(2)
5. 在Join表的时候使用相当类型的例,并将其索引 如果你的应用程序有很多 JOIN 查询,你应该确认两个表中Join的字段是被建过索引的.这样,MySQL内部会启动为你优化Join的SQL语句的机 ...
- 正則表達式--js使用案例
前言:在前端页面使用中.遇到日期格式的验证.開始使用了一款表单控件验证.可是不兼容!!并且使用起来还受到非常大约束.所以就决定自己写原生js. 为了完毕日期格式的验证.第一步,当然是学会使用正則表達式 ...
- Android4.42-Setting源代码分析之蓝牙模块Bluetooth(下)
接着上一篇Android4.42-Settings源代码分析之蓝牙模块Bluetooth(上) 继续蓝牙模块源代码的研究 THREE.蓝牙模块功能实现 switch的分析以及本机蓝牙重命名和可见性的分 ...
- DevExpress2011控件教程)编辑控件(comboBox,AspxCheckBox) 范例1
DevExpress2011控件教程)编辑控件(comboBox,AspxCheckBox) 范例1 AspxCheckBox 是一个检查编辑控件去展示特殊条件是否关闭或者打开.它一般会展示Yes/N ...
- mysql语法、特殊符号及正則表達式的使用
http://blog.csdn.net/pipisorry/article/details/46773545 sql语言 结构化的查询语言.(Structured Query Language),是 ...
- mac系统下为emacs设置中文字体,解决乱码问题
近期换了个系统,如今用mac系统. 当打开emacs后,中文支持的不是非常好.有的地方能显示.在.el文件的凝视里显示为口口口口口口口口这种框.例如以下图所看到的 找了半天.是由于中文字体的问题.仅仅 ...
- Page Design for Sexable Forum
Design Demo 1. Home of Sexable Forum 1.1 home page not logined. 1,2 home page logined. 2. Pages wit ...