[笔记][Java7并发编程实战手册]4.3 创建固定的线程执行器newFixedThreadPool线程池
来源:互联网 发布:川崎机器人编程手册 编辑:程序博客网 时间:2024/05/15 04:49
[笔记][Java7并发编程实战手册]系列目录
简介
newFixedThreadPool(int nThreads, ThreadFactory threadFactory)
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程,在需要时使用提供的 ThreadFactory 创建新线程。
newCachedThreadPool()创建的线程池的特性是:自动回收不使用的线程(终止并从缓存中移除那些已有 60 秒钟未被使用的线程),(在无可用线程的情况下)自动的为新来的task创建新线程。
正是因为这种特性,在小任务量,任务时间执行短的场景下能提高性能。然后如果在大量任务,且任务执行之间较长的场景中,系统将会超负荷。性能极低。
newFixedThreadPool(int nThreads) 就是来解决以上问题的。它创建一个固定大小的线程池,如果task任务数量大于nThreads数量,那么这些任务将在队列中排队,直到有可用线程再执行。
讲了2章了,可能有得人还不知道为什么要强转成ThreadPoolExecutor,可以看下面的源码,和下面的类图就明白了
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
newSingleThreadExecutor:
只创建一个线程的线程池。多余的task将以无界队列来运行。也就是阻塞到有可用线程才能运行。
示例
创建固定大小的线程池
场景描述:下面示例讲的是:创建一个固定大小的线程执行器线程池,然后循环创建几个task任务执行。观察线程数量和名称。
/** * Created by zhuqiang on 2015/8/25 0025. */public class Client { public static void main(String[] args) { ThreadPoolExecutor es = (ThreadPoolExecutor) Executors.newFixedThreadPool(3);// es.shutdown(); // 如果先关闭再执行任务,则会拒绝执行任务,抛出RejectedExecutionException异常 for (int i = 0; i < 10 ; i++) { es.execute(new Task(es,"task-"+i)); } es.shutdown(); }}class Task implements Runnable{ private ThreadPoolExecutor es; private String name; public Task(ThreadPoolExecutor es, String name) { this.es = es; this.name = name; } @Override public void run() { try { long timeout = (long) (Math.random() * 10); TimeUnit.SECONDS.sleep(timeout); System.out.println(Thread.currentThread().getName() + "...执行完成..task=" + name +" 耗时:" + timeout); } catch (InterruptedException e) { e.printStackTrace(); } }}
某一次的运行结果:
pool-1-thread-2...执行完成..task=task-1 耗时:0pool-1-thread-1...执行完成..task=task-0 耗时:3pool-1-thread-3...执行完成..task=task-2 耗时:4pool-1-thread-2...执行完成..task=task-3 耗时:5pool-1-thread-1...执行完成..task=task-4 耗时:5pool-1-thread-3...执行完成..task=task-5 耗时:7pool-1-thread-3...执行完成..task=task-8 耗时:0pool-1-thread-2...执行完成..task=task-6 耗时:8pool-1-thread-1...执行完成..task=task-7 耗时:7pool-1-thread-3...执行完成..task=task-9 耗时:8
结果说明:可以看到,创建了3个数量的线程池,在执行中,也只会使用这三个线程数量,而其他的则会阻塞等待执行。
创建固定大小的线程池的时候使用ThreadFactory
ThreadFactory的作用:构造一个新 Thread。实现也可能初始化属性、名称、守护程序状态、ThreadGroup 等等。
在写demo的时候,我认为最麻烦的就是,设置循环中创建的线程的join方法。 在没有使用线程池的时候,在循环中调用这个方法都麻烦,要么抛出异常,要么就只有再循环一次来单独设置。 就这个场景而言,使用ThreadFactory来就很简单了。 ——————– 好把,我以为在工厂中,自己调用join方法能行。但是测试过了。视乎没有效果。 那就只能看下用法。场景用途我暂时也不知道了
示例如下:
/** * Created by zhuqiang on 2015/8/25 0025. */public class Client { public static void main(String[] args) {// ThreadPoolExecutor es = (ThreadPoolExecutor) Executors.newFixedThreadPool(3); //1 该注释代码。和下面为使用工厂的对比。 ThreadPoolExecutor es = (ThreadPoolExecutor) Executors.newFixedThreadPool(3, new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setName("xxxx" + thread.getId()); //对新创建的线程做一些操作 return thread; } }); for (int i = 0; i < 10 ; i++) { es.execute(new Task(es,"task-"+i)); } es.shutdown(); }}class Task implements Runnable{ private ThreadPoolExecutor es; private String name; public Task(ThreadPoolExecutor es, String name) { this.es = es; this.name = name; } @Override public void run() { try { long timeout = (long) (Math.random() * 10); TimeUnit.SECONDS.sleep(timeout); System.out.println(Thread.currentThread().getName() + "...执行完成..task=" + name +" 耗时:" + timeout); } catch (InterruptedException e) { e.printStackTrace(); } }}
某一次的执行结果:
xxxx12...执行完成..task=task-0 耗时:3xxxx12...执行完成..task=task-3 耗时:2xxxx14...执行完成..task=task-2 耗时:6xxxx13...执行完成..task=task-1 耗时:7xxxx13...执行完成..task=task-6 耗时:0xxxx12...执行完成..task=task-4 耗时:4xxxx13...执行完成..task=task-7 耗时:6xxxx14...执行完成..task=task-5 耗时:7xxxx12...执行完成..task=task-8 耗时:5xxxx13...执行完成..task=task-9 耗时:8
- [笔记][Java7并发编程实战手册]4.3 创建固定的线程执行器newFixedThreadPool线程池
- [笔记][Java7并发编程实战手册]4.2 创建线程执行器newCachedThreadPool无界线程池
- Java7并发编程--4.1、创建线程执行器
- [笔记][Java7并发编程实战手册]第三章-线程同步辅助类-3.1概要
- [笔记][Java7并发编程实战手册][后补]1.线程管理
- java 通过Executors.newFixedThreadPool创建固定大小的线程执行器
- [笔记][Java7并发编程实战手册]4.9-4.10在执行器中控制任务的完成和取消任务FutureTask
- Java7并发编程--4、线程执行框架
- [笔记][Java7并发编程实战手册]4.7-4.8 在执行器中延迟执行或则周期执行任务ScheduledThreadPoolExecutor
- [笔记][Java7并发编程实战手册]4.4 在执行器中执行任务并返回结果Callable、Future
- [笔记][Java7并发编程实战手册]4.11-4.12在执行器中分离任务的启动和结果的处理和处理在执行器中被拒绝的任务
- [笔记][Java7并发编程实战手册]6.并发集合
- [笔记][Java7并发编程实战手册]7. 定制并发类
- [笔记][Java7并发编程实战手册]3.2 资源的并发访问控制Semaphore信号量
- [笔记][Java7并发编程实战手册]3.3 资源的多副本并发访问控制Semaphore
- [笔记][Java7并发编程实战手册]3.6 并发阶段任务的运行phaser
- [笔记][Java7并发编程实战手册]3.8 并发任务间的数据交换Exchanger
- [笔记][Java7并发编程实战手册]系列目录
- CS,七,软件工程
- Linux文件基本介绍
- 基本排序算法--快速排序
- 使用.NET中的XML注释(二) -- 创建帮助文档入门篇
- PorterDuff及Xfermode详解
- [笔记][Java7并发编程实战手册]4.3 创建固定的线程执行器newFixedThreadPool线程池
- Java线程状态知识点
- python--利用有道网址编写一个翻译句子的程序
- IOS启动动流程
- iOS学习(1)
- 基于node-red工具实现自定义节点
- iOS应用架构谈 网络层设计方案
- 沉默的阿福
- java的IO之字符流字节流