【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并发编程(您不知道的线程池操作) 这几篇博客,一直在谈线程,设想一下这个场景,如果并发的线程很多,然而每个线程如果执行的时间很多的话,这样的话,就会大量的降低系统的效率.这时候就可以采用线程池 ...
随机推荐
- oracle 基本语法(一)
1.基本语句: .查询每个部门工资最高的人的详细记录 select * from emp e,(select max(sal) max,deptno from emp group by deptno) ...
- CodeForces - 348A Mafia (巧妙二分)
传送门: http://codeforces.com/problemset/problem/348/A A. Mafia time limit per test 2 seconds memory li ...
- data-ng-click 指令
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- MVVM及框架的双向绑定
MVVM由以下三个内容组成 View:视图模板 Model:数据模型 ViewModel:作为桥梁负责沟通View和Model,自动渲染模板 在JQuery时期,如果需要刷新UI时,需要先取到对应的D ...
- if switch for while
---恢复内容开始--- 一.if 说明:判断表达式,看结果执行语句体 public class IfDemo2 { public static void main(Strin ...
- navicat 链接oracle时出现的各种问题
1.出现12514错误: 方法:在oracle的安装路径下找到tnsnames.ora文件(我的安装路径为E:\app\sa\product\12.2.0\dbhome_1\network\admin ...
- 1486: [HNOI2009]最小圈
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 3129 Solved: 1543[Submit][Status][Discuss] Descripti ...
- 构建高可靠hadoop集群之4-保全模式
本文主要翻译自http://hadoop.apache.org/docs/r2.8.0/hadoop-project-dist/hadoop-common/SecureMode.html 译注:之所以 ...
- JS日期去杠,日期转换String转Date
1.巧妙使用split()和join()替换字符串var str = '2014-05-05';var newstr = str.split('-').join("");split ...
- Maven命令参数
命令参数 备注 mvn -v --version 显示版本信息; mvn -V --show-version 显示版本信息后继续执行Maven其他目标; mvn -h --help 显示帮助信息; m ...
