[笔记][Java7并发编程实战手册]4.2 创建线程执行器newCachedThreadPool无界线程池
2015-08-24 22:27
489 查看
[笔记][Java7并发编程实战手册]系列目录
自动回收不使用的线程(终止并从缓存中移除那些已有 60 秒钟未被使用的线程),(在无可用线程的情况下)自动的为新来的task创建新线程。
使用场景:
在小任务量,任务时间执行短的场景下能提高性能。
在jdk api中的介绍如下一部分,其他的请查看api文档
ThreadPoolExecutor是一个一个 ExecutorService,它使用可能的几个池线程之一执行每个提交的任务,通常使用 Executors 工厂方法配置。
线程池可以解决两个不同问题:由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行任务集时使用的线程)的方法。每个 ThreadPoolExecutor 还维护着一些基本的统计数据,如完成的任务数。
为了便于跨大量上下文使用,此类提供了很多可调整的参数和扩展钩子 (hook)。但是,强烈建议程序员使用较为方便的 Executors 工厂方法构建服务:
1. Executors.newCachedThreadPool()(无界线程池,可以进行自动线程回收)
2. Executors.newFixedThreadPool(int)(固定大小线程池)
3. Executors.newSingleThreadExecutor()(单个后台线程),它们均为大多数使用场景预定义了设置。
要记得使用shutdown() 来关闭执行器,如果不关闭,则一直等待新任务的到来,该方法在api中的解释:按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。如果已经关闭,则调用没有其他作用。
上手使用伪代码:
某一次的运行结果:
结果说明
仔细看上面的线程名称,和task名称,可以看出来,3个任务只使用了2个线程。如果在更多的任务中,线程得到了复用。性能更好了
可以看到上面打印的信息。一些api打印出来的线程池中的一些任务信息。 没什么可说,先上手。再深入
简介
newCachedThreadPool()创建的线程池的特性是:自动回收不使用的线程(终止并从缓存中移除那些已有 60 秒钟未被使用的线程),(在无可用线程的情况下)自动的为新来的task创建新线程。
使用场景:
在小任务量,任务时间执行短的场景下能提高性能。
在jdk api中的介绍如下一部分,其他的请查看api文档
ThreadPoolExecutor是一个一个 ExecutorService,它使用可能的几个池线程之一执行每个提交的任务,通常使用 Executors 工厂方法配置。
线程池可以解决两个不同问题:由于减少了每个任务调用的开销,它们通常可以在执行大量异步任务时提供增强的性能,并且还可以提供绑定和管理资源(包括执行任务集时使用的线程)的方法。每个 ThreadPoolExecutor 还维护着一些基本的统计数据,如完成的任务数。
为了便于跨大量上下文使用,此类提供了很多可调整的参数和扩展钩子 (hook)。但是,强烈建议程序员使用较为方便的 Executors 工厂方法构建服务:
1. Executors.newCachedThreadPool()(无界线程池,可以进行自动线程回收)
2. Executors.newFixedThreadPool(int)(固定大小线程池)
3. Executors.newSingleThreadExecutor()(单个后台线程),它们均为大多数使用场景预定义了设置。
本章使用心得newCachedThreadPool()
使用Executors来构建预置服务。要记得使用shutdown() 来关闭执行器,如果不关闭,则一直等待新任务的到来,该方法在api中的解释:按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。如果已经关闭,则调用没有其他作用。
上手使用伪代码:
ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool(); //创建线程池执执行器服务 executor.execute(task); //把Runnable交给执行器执行 executor.shutdown(); //申请关闭执行器
简单的示例示例
场景描述:以下示例就是演示了,把一组线程交给执行器执行,在执行器中打印执行器中线程池中的一些任务信息。/** * Created by zhuqiang on 2015/8/24 0024. */ public class Client { public static void main(String[] args) throws InterruptedException { Service s = new Service(); for (int i = 0; i < 3; i++) { Task task = new Task(new Date(), "task" + i); TimeUnit.SECONDS.sleep(3); // 休眠3秒,以便等待有任务执行完的线程。在信息里面能看到更丰富的 执行器的管理信息 s.executorTask(task); } s.endService(); // 1 如果注释此代码,本程序将挂起。不会结束 } } /** 模拟任务类*/ class Task implements Runnable{ private Date initDate; //初始化时间 private String name; //任务名称 public Task(Date initDate, String name) { this.initDate = initDate; this.name = name; } @Override public void run() { Thread t = Thread.currentThread(); System.out.printf(" start-------------%s,任务名称:%s,时间:%s\n", t.getName(),this.name,initDate); try { long time = (long)(Math.random() * 10); //模拟工作时间 TimeUnit.SECONDS.sleep(time); System.out.printf(" end-------------%s,任务名称:%s,耗时:%s\n", t.getName(),this.name,time); }catch (Exception e){ e.printStackTrace(); } } } /** 服务类,接收每一个任务*/ class Service{ private ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool(); /** 接受任务,直接丢给了 线程池执行*/ public void executorTask(Task task){ System.out.println("service:接收了一个task"); executor.execute(task); System.out.printf("service:pool执行器中线程中实际的线程数量:%d,执行器中正在执行任务的线程数量:%d,执行器中已经完成的任务数量:%d\n",executor.getPoolSize(),executor.getActiveCount(),executor.getCompletedTaskCount()); } /** */ public void endService(){ System.out.printf("service-----------------shutdown--------------:pool执行器中线程中实际的线程数量:%d,执行器中正在执行任务的线程数量:%d,执行器中已经完成的任务数量:%d\n",executor.getPoolSize(),executor.getActiveCount(),executor.getCompletedTaskCount()); executor.shutdown(); } }
某一次的运行结果:
service:接收了一个task start-------------pool-1-thread-1,任务名称:task0,时间:Mon Aug 24 22:33:23 CST 2015 service:pool执行器中线程中实际的线程数量:1,执行器中正在执行任务的线程数量:1,执行器中已经完成的任务数量:0 service:接收了一个task service:pool执行器中线程中实际的线程数量:2,执行器中正在执行任务的线程数量:2,执行器中已经完成的任务数量:0 start-------------pool-1-thread-2,任务名称:task1,时间:Mon Aug 24 22:33:26 CST 2015 end-------------pool-1-thread-1,任务名称:task0,耗时:4 service:接收了一个task service:pool执行器中线程中实际的线程数量:2,执行器中正在执行任务的线程数量:1,执行器中已经完成的任务数量:1 start-------------pool-1-thread-1,任务名称:task2,时间:Mon Aug 24 22:33:29 CST 2015 service-----------------shutdown--------------:pool执行器中线程中实际的线程数量:2,执行器中正在执行任务的线程数量:2,执行器中已经完成的任务数量:1 end-------------pool-1-thread-2,任务名称:task1,耗时:4 end-------------pool-1-thread-1,任务名称:task2,耗时:9
结果说明
仔细看上面的线程名称,和task名称,可以看出来,3个任务只使用了2个线程。如果在更多的任务中,线程得到了复用。性能更好了
可以看到上面打印的信息。一些api打印出来的线程池中的一些任务信息。 没什么可说,先上手。再深入
相关文章推荐
- 【Java基础】--再谈面向对象
- Java IO流总览
- 关于Dynamo-All Things Distributed
- java:回调函数
- [笔记][Java7并发编程实战手册]系列第四章 4.1 简介
- java新手笔记31 集合实现类
- JAVA问题总结之6--强制转换损失精度分析
- 统计字符串中每个字母的个数
- Java之旅hibernate(8)——基本关系映射
- spring boot demo( 获取一个RESTful web service)
- spring的propogation(传播机制)
- Eclipse 搭建 Maven Web项目
- Java基础学习正则表达式
- Java设计模式------单例设计模式
- Java内存
- Java的Calendar
- Java多线程之一
- 关于java中Double类型的运算精度问题
- 【JavaSE】day03_Date、SimpleDateFormat、Calendar、Collection
- java新手笔记30 集合