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. 手写数字识别的k-近邻算法实现

    (本文为原创,请勿在未经允许的情况下转载) 前言 手写字符识别是机器学习的入门问题,k-近邻算法(kNN算法)是机器学习的入门算法.本文将介绍k-近邻算法的原理.手写字符识别问题分析.手写字符识别的k ...

  2. 【洛谷P2216】[HAOI2007]理想的正方形

    理想的正方形 [题目描述] 一个a*b的矩阵,从中取一个n*n的子矩阵,使所选矩阵中的最大数与最小数的差最小. 思路: 二维的滑动窗口 对于每行:用一个单调队列维护,算出每个长度为n的区间的最大值和最 ...

  3. Notepad++ 插件之 TextFX (安装及作用)

    <安装:打开 notepad++  插件 -> Plugin Manager -> Show Plugin Manager -> available ->选中 TextF ...

  4. scala容器使用

    花了两个小时左右,学习了一下scala语言, 由于scala运行在jvm之上, 可以使用java容器也可以使用scala自带的容器. import java.util import java.util ...

  5. MR中简单实现自定义的输入输出格式

    import java.io.DataOutput; import java.io.IOException; import java.util.HashMap; import java.util.Ma ...

  6. lucene&solr学习——solr学习(一)

    1.什么是solr solr是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文检索服务器.Solr提供了比lucene风味丰富的查询语言,同时实现了可配置,可扩展,并对索 ...

  7. 基于socketserver模块实现并发的套接字(tcp、udp)

    tcp服务端:import socketserver class MyHandler(socketserver.BaseRequestHandler): def handle(self): #通信循环 ...

  8. 仿制用友U8界面

    unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  9. Idea 2017 激活方法

    http://www.cnblogs.com/suiyueqiannian/p/6754091.html

  10. Windows Server 2012下手动配置IIS的文件夹访问权限

    当新建一个website的时候,一般情况下IIS对相应的物理文件夹的访问权限是不够的. 针对匿名认证(anonymous authentication)需要: 打开文件夹properties-> ...