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并发编程实战】第六章:线程池的更多相关文章

  1. Java并发编程实战 第8章 线程池的使用

    合理的控制线程池的大小: 下面内容来自网络.不过跟作者说的一致.不想自己敲了.留个记录. 要想合理的配置线程池的大小,首先得分析任务的特性,可以从以下几个角度分析: 任务的性质:CPU密集型任务.IO ...

  2. Java并发编程实战---第六章:任务执行

    废话开篇 今天开始学习Java并发编程实战,很多大牛都推荐,所以为了能在并发编程的道路上留下点书本上的知识,所以也就有了这篇博文.今天主要学习的是任务执行章节,主要讲了任务执行定义.Executor. ...

  3. 《Java并发编程实战》第八章 线程池的使用 读书笔记

    一.在任务与运行策略之间的隐性解耦 有些类型的任务须要明白地指定运行策略,包含: . 依赖性任务.依赖关系对运行策略造成约束.须要注意活跃性问题. 要求线程池足够大,确保任务都能放入. . 使用线程封 ...

  4. java并发编程实战:第八章----线程池的使用

    一.在任务和执行策略之间隐性耦合 Executor框架将任务的提交和它的执行策略解耦开来.虽然Executor框架为制定和修改执行策略提供了相当大的灵活性,但并非所有的任务都能适用所有的执行策略. 依 ...

  5. java并发编程(十六)----(线程池)java线程池的使用

    上节我们简单介绍了线程池,这次我们就来使用一下.Executors提供四种线程池,分别是:newCachedThreadPool,newFixedThreadPool ,newScheduledThr ...

  6. java并发编程实战:第二章----线程安全性

    一个对象是否需要是线程安全的取决于它是否被多个线程访问. 当多个线程访问同一个可变状态量时如果没有使用正确的同步规则,就有可能出错.解决办法: 不在线程之间共享该变量 将状态变量修改为不可变的 在访问 ...

  7. 《Java并发编程实战》第二章 线程安全性 读书笔记

    一.什么是线程安全性 编写线程安全的代码 核心在于要对状态訪问操作进行管理. 共享,可变的状态的訪问 - 前者表示多个线程訪问, 后者声明周期内发生改变. 线程安全性 核心概念是正确性.某个类的行为与 ...

  8. 《Java并发编程实战》第二章 线程安全 札记

    一个.什么是线程安全 编写线程安全的代码 其核心是管理国事访问的操作. 共享,可变的状态的訪问 - 前者表示多个线程訪问, 后者声明周期内发生改变. 线程安全性 核心概念是正确性.某个类的行为与其规范 ...

  9. Java并发编程实战 第2章 线程安全性

    编写线程安全的 代码,核心在与对共享的和可变的对象的状态的访问. 如果多个线程访问一个可变的对象时没有使用同步,那么就会出现错误.在这种情况下,有3中方式可以修复这个问题: 不在线程之间共享该状态变量 ...

  10. Java并发编程(您不知道的线程池操作)

    Java并发编程(您不知道的线程池操作) 这几篇博客,一直在谈线程,设想一下这个场景,如果并发的线程很多,然而每个线程如果执行的时间很多的话,这样的话,就会大量的降低系统的效率.这时候就可以采用线程池 ...

随机推荐

  1. Cesium.js学习第二天(立方体)

    var viewer = new Cesium.Viewer('cs'); viewer.entities.add({//图标 position: Cesium.Cartesian3.fromDegr ...

  2. 【洛谷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 ...

  3. U盘空间释放

    U盘做成启动盘后,怎么释放空间,恢复到原来的容量.这里有个帖子,我觉得很方便,不用安装什么东西,简单直接. http://blog.sina.com.cn/s/blog_68f6e8a901014cv ...

  4. vue组件原生事件以及路由

    1.组件 组件就是可以扩展HTML元素,封装可重用的HTML代码,可以将组件看作自定义的HTML元素 1.1组件注册 全局注册: 组件注册时,需要给他一个名字,如下: Vue.component('m ...

  5. Unity 游戏框架搭建 (十一) 简易AssetBundle打包工具(一)

    最近在看Unity官方的AssetBundle(以下简称AB)的教程,也照着做了一遍,不过做出来的AssetBundleManager的API设计得有些不太习惯.目前想到了一个可行的解决方案.AB相关 ...

  6. mysql if...else 的使用

    select case when tca.id = '3' then 'vw' else epc_code end as epccode,tfp.product_id, tfp.vender, tfp ...

  7. [JSOI2010]Group 部落划分 Group

    Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 3661  Solved: 1755[Submit][Status][Discuss] Descripti ...

  8. ab工具测试 swoole 和 ngixn+php-fpm 的并发对比

    测试样例: 执行的一条sql记录的1w次插入分两组: 一组用nginx+pfm 来执行, 一组用swoole 来执行 公平性保证前提: @1.为了保证公平性, 在nginx里把 access_log, ...

  9. mysql-新增表前判断同名表是否存在

    新增多个表时,如果有同名表会报错,导致其中一个表不能正确创建,此时可以用以下语句进行判断: DROP TABLE IF EXISTS USER; --判断表是否存在,如果存在就删除! CREATE T ...

  10. 分布式系统的CAP(Redis)

    CAP理论就是说在分布式存储系统中,最多只能实现上面的两点.而由于当前的网络硬件肯定会出现延迟丢包等问题,所以 分区容忍性是我们必须需要实现的. 所以我们只能在一致性和可用性之间进行权衡,没有NoSQ ...