【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并发编程(您不知道的线程池操作) 这几篇博客,一直在谈线程,设想一下这个场景,如果并发的线程很多,然而每个线程如果执行的时间很多的话,这样的话,就会大量的降低系统的效率.这时候就可以采用线程池 ...
随机推荐
- Cesium.js学习第二天(立方体)
var viewer = new Cesium.Viewer('cs'); viewer.entities.add({//图标 position: Cesium.Cartesian3.fromDegr ...
- 【洛谷P1118】数字三角形
数字三角形 题目链接 4 16 3 1 2 4 3 1 2 4 (3+1) (1+2) (2+4)(3+1+1+2) (1+2+2+4) (3+1+1+1+2+2+2+4)16=1*3+3*1+3*2 ...
- U盘空间释放
U盘做成启动盘后,怎么释放空间,恢复到原来的容量.这里有个帖子,我觉得很方便,不用安装什么东西,简单直接. http://blog.sina.com.cn/s/blog_68f6e8a901014cv ...
- vue组件原生事件以及路由
1.组件 组件就是可以扩展HTML元素,封装可重用的HTML代码,可以将组件看作自定义的HTML元素 1.1组件注册 全局注册: 组件注册时,需要给他一个名字,如下: Vue.component('m ...
- Unity 游戏框架搭建 (十一) 简易AssetBundle打包工具(一)
最近在看Unity官方的AssetBundle(以下简称AB)的教程,也照着做了一遍,不过做出来的AssetBundleManager的API设计得有些不太习惯.目前想到了一个可行的解决方案.AB相关 ...
- mysql if...else 的使用
select case when tca.id = '3' then 'vw' else epc_code end as epccode,tfp.product_id, tfp.vender, tfp ...
- [JSOI2010]Group 部落划分 Group
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 3661 Solved: 1755[Submit][Status][Discuss] Descripti ...
- ab工具测试 swoole 和 ngixn+php-fpm 的并发对比
测试样例: 执行的一条sql记录的1w次插入分两组: 一组用nginx+pfm 来执行, 一组用swoole 来执行 公平性保证前提: @1.为了保证公平性, 在nginx里把 access_log, ...
- mysql-新增表前判断同名表是否存在
新增多个表时,如果有同名表会报错,导致其中一个表不能正确创建,此时可以用以下语句进行判断: DROP TABLE IF EXISTS USER; --判断表是否存在,如果存在就删除! CREATE T ...
- 分布式系统的CAP(Redis)
CAP理论就是说在分布式存储系统中,最多只能实现上面的两点.而由于当前的网络硬件肯定会出现延迟丢包等问题,所以 分区容忍性是我们必须需要实现的. 所以我们只能在一致性和可用性之间进行权衡,没有NoSQ ...
