Java 线程池

Executors提供了几种线程池实现?

5个,分别如下

1、newCachedThreadPool:创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。(线程最大并发数不可控制)
2、newFixedThreadPool:创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3、newScheduledThreadPool:创建一个定长线程池,支持定时及周期性任务执行。
4、newSingleThreadExecutor:创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
5、newWorkStealingPool:jdk1.8新增,创建持有足够线程的线程池来支持给定的并行级别,并通过使用多个队列,减少竞争,它需要穿一个并行级别的参数,如果不传,则被设定为默认的CPU数量。

使用线程池的好处

a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
c. 提供定时执行、定期执行、单线程、并发数控制等功能。

ThreadPoolExecutor机制

看看上面几种线程池的实现代码:

1、newCachedThreadPool

  1. public static ExecutorService newCachedThreadPool() {
  2. return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
  3. 60L, TimeUnit.SECONDS,
  4. new SynchronousQueue<Runnable>());
  5. }

2、newFixedThreadPool

  1. public static ExecutorService newFixedThreadPool(int nThreads) {
  2. return new ThreadPoolExecutor(nThreads, nThreads,
  3. 0L, TimeUnit.MILLISECONDS,
  4. new LinkedBlockingQueue<Runnable>());
  5. }

3、newScheduledThreadPool

  1. public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
  2. return new ScheduledThreadPoolExecutor(corePoolSize);
  3. }
  4.  
  5. public ScheduledThreadPoolExecutor(int corePoolSize) {
  6. super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
  7. new DelayedWorkQueue());
  8. }
  9.  
  10. public ThreadPoolExecutor(int corePoolSize,
  11. int maximumPoolSize,
  12. long keepAliveTime,
  13. TimeUnit unit,
  14. BlockingQueue<Runnable> workQueue) {
  15. this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
  16. Executors.defaultThreadFactory(), defaultHandler);
  17. }

4、newSingleThreadExecutor

  1. public static ExecutorService newSingleThreadExecutor() {
  2. return new FinalizableDelegatedExecutorService
  3. (new ThreadPoolExecutor(1, 1,
  4. 0L, TimeUnit.MILLISECONDS,
  5. new LinkedBlockingQueue<Runnable>()));
  6. }

5、newWorkStealingPool

  1. public static ExecutorService newWorkStealingPool() {
  2. return new ForkJoinPool
  3. (Runtime.getRuntime().availableProcessors(),
  4. ForkJoinPool.defaultForkJoinWorkerThreadFactory,
  5. null, true);
  6. }

可以看出前四种线程池最终都是返回了ThreadPoolExecutor对象,最后一个返回的ForkJoinPool是jdk1.7才新增的。

下面来看一下ThreadPoolExecutor的构造方法:

  1. public ThreadPoolExecutor(int corePoolSize,//核心线程池大小
  2. int maximumPoolSize,//最大线程池大小
  3. long keepAliveTime,//线程池中超过corePoolSize数目的空闲线程最大存活时间;可以allowCoreThreadTimeOut(true)成为核心线程的有效时间
  4. TimeUnit unit,//keepAliveTime的时间单位
  5. BlockingQueue<Runnable> workQueue,//阻塞任务队列
  6. ThreadFactory threadFactory,//线程工厂
  7. RejectedExecutionHandler handler) {//当提交任务数超过maxmumPoolSize+workQueue之和时,任务会交给RejectedExecutionHandler来处理
  8. if (corePoolSize < 0 ||
  9. maximumPoolSize <= 0 ||
  10. maximumPoolSize < corePoolSize ||
  11. keepAliveTime < 0)
  12. throw new IllegalArgumentException();
  13. if (workQueue == null || threadFactory == null || handler == null)
  14. throw new NullPointerException();
  15. this.corePoolSize = corePoolSize;
  16. this.maximumPoolSize = maximumPoolSize;
  17. this.workQueue = workQueue;
  18. this.keepAliveTime = unit.toNanos(keepAliveTime);
  19. this.threadFactory = threadFactory;
  20. this.handler = handler;
  21. }

再看一下ForkJoinPool的构造方法

  1. public ForkJoinPool(int parallelism,
  2. ForkJoinWorkerThreadFactory factory,
  3. UncaughtExceptionHandler handler,
  4. boolean asyncMode) {
  5. this(checkParallelism(parallelism),
  6. checkFactory(factory),
  7. handler,
  8. asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
  9. "ForkJoinPool-" + nextPoolId() + "-worker-");
  10. checkPermission();
  11. }

ThreadPoolExecutor和ForkJoinPool都继承了AbstractExecutorService

重点讲解: 
其中比较容易让人误解的是:corePoolSize,maximumPoolSize,workQueue之间关系。

1.当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。 
2.当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行 
3.当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务 
4.当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理 
5.当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程 
6.当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

更多ThreadPoolExecutor的使用:http://www.cnblogs.com/shamo89/p/6694133.html

那么学会使用ThreadPoolExecutor的参数后,我们就可以不用局限于最上面那四种线程池,可以按照需要来构建自己的线程池;

ThreadFactory的使用

Executors提供了一个默认的ThreadFactory,我们可以根据需求是否使用它,或者继承它,或者实现ThreadFactory接口来自定义线程工厂需求。

DefaultThreadFactory的源码

  1. /**
  2. * The default thread factory
  3. */
  4. static class DefaultThreadFactory implements ThreadFactory {
  5. private static final AtomicInteger poolNumber = new AtomicInteger(1);// 线程数量,也用于给生成的线程来命名
  6. private final ThreadGroup group;
  7. private final AtomicInteger threadNumber = new AtomicInteger(1);
  8. private final String namePrefix;// 线程名前缀
  9.  
  10. DefaultThreadFactory() {// 构造方法
  11. SecurityManager s = System.getSecurityManager();
  12. group = (s != null) ? s.getThreadGroup() :
  13. Thread.currentThread().getThreadGroup();// 初始化ThreadGroup
  14. namePrefix = "pool-" +
  15. poolNumber.getAndIncrement() +
  16. "-thread-";// 初始化线程名
  17. }
  18.  
  19. public Thread newThread(Runnable r) {// 实现接口方法
  20. Thread t = new Thread(group, r,
  21. namePrefix + threadNumber.getAndIncrement(),
  22. 0);// 新建线程
  23. if (t.isDaemon())// 判断是否为守护线程
  24. t.setDaemon(false);
  25. if (t.getPriority() != Thread.NORM_PRIORITY)// 设置线程的优先级为默认
  26. t.setPriority(Thread.NORM_PRIORITY);
  27. return t;
  28. }
  29. }

可以看出,默认的DefaultThreadFactory实现了工厂类生成线程的一些基础设置。

PrivilegedThreadFactory的介绍

PrivilegedThreadFactory继承了DefaultThreadFactory,它主要是用于创建与当前线程具有相同的权限的新线程。具体源码可以自行查看。

Ehcache里的NamedThreadFactory

在ehcache的包net.sf.ehcache.util里,有个NamedThreadFactory,功能实现和DefaultThreadFactory类似,它是直接实现ThreadFactory接口。

<T> Callable<T> callable(Runnable task, T result)

包装runnable,使得线程具有返回值,result可以自定义。

java.util.concurrent.Executors类的常用方法介绍的更多相关文章

  1. java.util.concurrent.atomic 类包详解

    java.util.concurrent包分成了三个部分,分别是java.util.concurrent.java.util.concurrent.atomic和java.util.concurren ...

  2. java.util.concurrent常用类(CountDownLatch,Semaphore,CyclicBarrier,Future)

    CyclicBarrier CyclicBarrier是用来一个关卡来阻挡住所有线程,等所有线程全部执行到关卡处时,再统一执行下一步操作.假设一个场景:每个线程代表一个跑步运动员,当运动员都准备好后, ...

  3. Java 并发工具包 java.util.concurrent 用户指南

    1. java.util.concurrent - Java 并发工具包 Java 5 添加了一个新的包到 Java 平台,java.util.concurrent 包.这个包包含有一系列能够让 Ja ...

  4. Java并发编程-并发工具包(java.util.concurrent)使用指南(全)

    1. java.util.concurrent - Java 并发工具包 Java 5 添加了一个新的包到 Java 平台,java.util.concurrent 包.这个包包含有一系列能够让 Ja ...

  5. Java_并发工具包 java.util.concurrent 用户指南(转)

    译序 本指南根据 Jakob Jenkov 最新博客翻译,请随时关注博客更新:http://tutorials.jenkov.com/java-util-concurrent/index.html.本 ...

  6. Java 并发工具包 java.util.concurrent 大全

    1. java.util.concurrent - Java 并发工具包 Java 5 添加了一个新的包到 Java 平台,java.util.concurrent 包.这个包包含有一系列能够让 Ja ...

  7. 1. java.util.concurrent - Java 并发工具包

    1. java.util.concurrent - Java 并发工具包 Java 5 添加了一个新的包到 Java 平台,java.util.concurrent 包.这个包包含有一系列能够让 Ja ...

  8. java.util.concurrent包详细分析--转

    原文地址:http://blog.csdn.net/windsunmoon/article/details/36903901 概述 Java.util.concurrent 包含许多线程安全.测试良好 ...

  9. java.util.concurrent 多线程框架

    http://daoger.iteye.com/blog/142485 JDK5中的一个亮点就是将Doug Lea的并发库引入到Java标准库中.Doug Lea确实是一个牛人,能教书,能出书,能编码 ...

随机推荐

  1. CRM导入组织报实例名称必须与计算机名称相同的问题

    今天采用P2V拷贝了一台CRM数据库到虚机上,因为要加域必须得把计算机名改了,然后再重新导入组织的时候报错了:"实例名称必须与计算机名称相同",google了下没有匹配的问题答案, ...

  2. Remove Google Play Games libraries on iOS (Unity3D开发之二十一)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/48313653 ...

  3. android本地音乐播放器

    乐乐音乐播放器更新到2.0版本了,之前1.0版本更多的是试验性实践,这次更新的2.0版本,更多的是将1.0的功能移植到2.0,在界面和皮肤风格上,参考了 天天动听 界面,在歌词显示方面 与 1.0 版 ...

  4. 巧用FineReport搭建成本管控监测系统

    一.应用背景 企业在近几年快速发展,规模也越来越大,而信息传递与反馈手段却仍然比较落后,随着信息技术的不断发展,人们开始通过尝试利用技术手段改善这种环境.企业的项目不断增多,而作为高层管理者,通过层级 ...

  5. 深入理解JNI

    深入理解JNI 最近在学习android底层的一些东西,看了一些大神的博客,整体上有了一点把握,也产生了很多疑惑,于是再次把邓大神的深入系列翻出来仔细看看,下面主要是一些阅读笔记. JNI概述 JNI ...

  6. LeetCode之旅(22)-House Robber

    题目: You are a professional robber planning to rob houses along a street. Each house has a certain am ...

  7. windows from 手风琴

    public class OutlookBar : Panel { private int SelectedBandHeight { get; set; } public int ButtonHeig ...

  8. MariaDB/MySQL用户和权限管理

    本文目录: 1.权限验证 1.1 权限表 1.2 图解认证和权限分配的两个阶段 1.3 权限生效时机 2.用户管理 2.1 创建用户 2.2 create user和alter user 2.3 记录 ...

  9. two sum II

    Given an array of integers that is already sorted in ascending order, find two numbers such that the ...

  10. java垃圾回收总结(2)

    java垃圾回收总结(2)   上一篇文章 介绍了jvm虚拟机运行时内存结构以及如何标识需要回收的对象,这一节主要讲解垃圾回收的基本算法. 基本上 jvm内存回收有三种 基本算法 标记-清除 标记清除 ...