【java并发编程实战】第六章:线程池
1.线程池
众所周知创建大量线程时代价是非常大的:
- 线程的生命周期开销非常大:创建需要时间,导致延迟处理请求,jvm需要分配空间。
- 资源消耗:线程需要占用空间,如果线程数大于可用的处理器数量,那么线程就会闲置,这给Gc造成压力。线程在竞争cpu的时候也会造成性能开销,所以线程不是越多越好,使用不当并不会增加运行效率。
- 稳定性:使用不当会造成内存溢出。
继而就引申出线程池。
1.1线程池的创建
Executors框架:静态方法创建
- newCachedThreadPool:创建可变线程数的线程池。有空闲的时候会回收。
- newFixedThreadPool:创建固定线程数的线程池。
- newScheduledThreadPool:创建固定数量线程池,以延时、定时的方式执行。
- newSingleThreadExecutor:创建单线程线程池。
Executors框架:
生命周期:运行->关闭->已终止
Executor扩展了ExecutorSerivice接口。提供了平缓关闭接口的方法。调用shutdown方法后会拒绝新增任务,进入关闭状态。等待所有任务处理完进入已终止。showdownNow会立刻进入已终止。调用awaitTermination会立刻调用shutdown等待关闭后返回同步关闭状态。
2.callable和future
future异步返回线程计算结果。callable可以以泛型的形式显示定义返回异步返回类型。
下面介绍一个例子:
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(1000L);
//return the thread name executing this callable task
return Thread.currentThread().getName();
}
public static void main(String args[]){
//Get ExecutorService from Executors utility class, thread pool size is 10
ExecutorService executor = Executors.newFixedThreadPool(10);
//create a list to hold the Future object associated with Callable
Queue<Future<String>> list = new LinkedBlockingQueue<>();
//Create MyCallable instance
Callable<String> callable = new MyCallable();
for(int i=0; i< 100; i++){
//submit Callable tasks to be executed by thread pool
Future<String> future = executor.submit(callable);
//add Future to the list, we can get return value using Future
list.add(future);
}
while (true) {
Future fut = list.poll();
try {
if (fut.isDone()) {
//print the return value of Future, notice the output delay in console
// because Future.get() waits for task to get completed
System.out.println(new Date()+ "::"+fut.get());
} else {
list.add(fut);
}
} catch (InterruptedException | ExecutionException | CancellationException e ) {
e.printStackTrace();
}
}
}
}
其中,当任务执行完成,调用get会返回Exception。如果么有完成,那么进入阻塞状态直至返回。如果执行过程中抛出异常,Executors会封装成ExecutionException重新抛出,通过getCause获取原始异常。如果任务被取消,就会抛出CancellationException。
3.completionService
轮询的方式太低效,可以考虑completionService
public class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(1000L);
return Thread.currentThread().getName();
}
public static void main(String args[]){
//
ExecutorService executor = Executors.newFixedThreadPool(10);
ExecutorCompletionService<String> stringExecutorCompletionService = new ExecutorCompletionService<>(executor);
Queue<Future<String>> list = new LinkedBlockingQueue<>();
Callable<String> callable = new MyCallable();
for(int i=0; i< 100; i++){
Future<String> future = stringExecutorCompletionService.submit(callable);
list.add(future);
}
while (true) {
try {
Future<String> take = stringExecutorCompletionService.take();
String s = take.get();
System.out.println(s);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
}
// 待补充分析源码。
4.为线程的返回值设置时限。
Future.class

如果get超过等待时间讲抛出timeoutexception
【java并发编程实战】第六章:线程池的更多相关文章
- Java并发编程实战 第8章 线程池的使用
合理的控制线程池的大小: 下面内容来自网络.不过跟作者说的一致.不想自己敲了.留个记录. 要想合理的配置线程池的大小,首先得分析任务的特性,可以从以下几个角度分析: 任务的性质:CPU密集型任务.IO ...
- Java并发编程实战---第六章:任务执行
废话开篇 今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文.今天主要学习的是任务执行章节,主要讲了任务执行定义.Executor. ...
- 《Java并发编程实战》第八章 线程池的使用 读书笔记
一.在任务与运行策略之间的隐性解耦 有些类型的任务须要明白地指定运行策略,包含: . 依赖性任务.依赖关系对运行策略造成约束.须要注意活跃性问题. 要求线程池足够大,确保任务都能放入. . 使用线程封 ...
- java并发编程实战:第八章----线程池的使用
一.在任务和执行策略之间隐性耦合 Executor框架将任务的提交和它的执行策略解耦开来.虽然Executor框架为制定和修改执行策略提供了相当大的灵活性,但并非所有的任务都能适用所有的执行策略. 依 ...
- java并发编程(十六)----(线程池)java线程池的使用
上节我们简单介绍了线程池,这次我们就来使用一下.Executors提供四种线程池,分别是:newCachedThreadPool,newFixedThreadPool ,newScheduledThr ...
- java并发编程实战:第二章----线程安全性
一个对象是否需要是线程安全的取决于它是否被多个线程访问. 当多个线程访问同一个可变状态量时如果没有使用正确的同步规则,就有可能出错.解决办法: 不在线程之间共享该变量 将状态变量修改为不可变的 在访问 ...
- 《Java并发编程实战》第二章 线程安全性 读书笔记
一.什么是线程安全性 编写线程安全的代码 核心在于要对状态訪问操作进行管理. 共享,可变的状态的訪问 - 前者表示多个线程訪问, 后者声明周期内发生改变. 线程安全性 核心概念是正确性.某个类的行为与 ...
- 《Java并发编程实战》第二章 线程安全 札记
一个.什么是线程安全 编写线程安全的代码 其核心是管理国事访问的操作. 共享,可变的状态的訪问 - 前者表示多个线程訪问, 后者声明周期内发生改变. 线程安全性 核心概念是正确性.某个类的行为与其规范 ...
- Java并发编程实战 第2章 线程安全性
编写线程安全的 代码,核心在与对共享的和可变的对象的状态的访问. 如果多个线程访问一个可变的对象时没有使用同步,那么就会出现错误.在这种情况下,有3中方式可以修复这个问题: 不在线程之间共享该状态变量 ...
- Java并发编程(您不知道的线程池操作)
Java并发编程(您不知道的线程池操作) 这几篇博客,一直在谈线程,设想一下这个场景,如果并发的线程很多,然而每个线程如果执行的时间很多的话,这样的话,就会大量的降低系统的效率.这时候就可以采用线程池 ...
随机推荐
- js点赞效果图
点赞时点赞图标会发生变化. html部分: <img src="img/icon_thumb_up.png" id="imgs1" style=" ...
- SpringBoot非官方教程 | 第三篇:SpringBoot用JdbcTemplates访问Mysql
转载请标明出处: 原文首发于https://www.fangzhipeng.com/springboot/2017/07/11/springboot3-JdbcTemplates-Mysql/ 本文出 ...
- Oracle四舍五入,向上取整,向下取整
用oracle sql对数字进行操作: 取上取整.向下取整.保留N位小数.四舍五入.数字格式化 取整(向下取整): select floor(5.534) from dual; select trun ...
- css选择器有哪些
css的选择器是还是比较富的,主要的css选择器如下: 标签选择器(如:body,div,p,ul,li) .类选择器(如:class="head",class="hea ...
- 小B的询问(莫队)
题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重 ...
- 魔板 Magic Squares(广搜,状态转化)
题目背景 在成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 题目描述 我们知道魔板的每一个方格都有一种颜色.这8种颜 ...
- Elasticsearch 常用API
1. Elasticsearch 常用API 1.1.数据输入与输出 1.1.1.Elasticsearch 文档 #在 Elasticsearch 中,术语 文档 有着特定的含义.它是指最顶 ...
- aioysql(异步操作MySQL)-python
python异步IO初探 探索异步IO执之前,先说说IO的种类 阻塞IO最简单,即读写数据时,需要等待操作完成,才能继续执行.进阶的做法就是用多线程来处理需要IO的部分,缺点是开销会有些大. 非阻塞I ...
- mysql5.7数据库与5.7之前版本比较
数据库初始化方式变更 <5.7 版本 mysql_install_db >5.7 版本 bin/mysqld --initialize --user =mysql --basedir=/u ...
- jenkins邮件发送jmeter接口测试报告
在Jenkins中配置实现邮件通知,Jenkins提供了两种方式的配置. 一种是Jenkins内置默认的邮件通知,但是它本身有很多局限性,比如它的邮件通知无法提供详细的邮件内容.无法定义发送邮件的格式 ...
