2019独角兽企业重金招聘Python工程师标准>>>

为什么要使用线程池创建线程?
    使用线程池的好处是减少在创建和销毁线程上所花的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
为什么线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式?
     Executors 返回的线程池对象的弊端如下:
        1) FixedThreadPool 和 SingleThreadPool :
        允许的请求队列长度为 Integer.MAX_VALUE ,可能会堆积大量的请求,从而导致 OOM 。
        2) CachedThreadPool 和 ScheduledThreadPool :
        允许的创建线程数量为 Integer.MAX_VALUE ,可能会创建大量的线程,从而导致 OOM 。
以上内容摘自阿里巴巴Java开发手册-编程规约-并发处理

下面用一个简单的例子演示使用ThreadPoolExecutor创建一个线程池

public static void main(String[] args){//创建线程工厂ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("test-pool-%d").build();//创建线程池ThreadPoolExecutor threadPool = new ThreadPoolExecutor(10, 10, 0L,TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(1024), threadFactory, new ThreadPoolExecutor.AbortPolicy());//执行10个线程for(int i=0;i<10;i++) {threadPool.execute(() -> {System.out.println(Thread.currentThread().getName());try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}});}//关闭线程池,不在接受新任务threadPool.shutdown();}

我们先看ThreadPoolExecutor的构造方法,ThreadPoolExecutor提供了三个构造方法,我们看参数最全的这个:

/*** 参数意义:* corePoolSize:核心线程数量,线程池中常存的线程数量,即使这些线程是空闲状态;*               但如果我们设置了allowCoreThreadTimeOut这个参数为true,*               这时核心线程将在空闲超过keepAliveTime后被终止* maximumPoolSize:最大线程数量,即线程池中允许的最大线程数* keepAliveTime:多余线程存活时间,当池中线程数大于核心数时,多余空闲线程处于空闲状态的时间不会超过这个时间,*                即多余的空闲线程超过这个时间就会被终止* unit:keepAliveTime参数的时间单位* workQueue:任务队列,BlockingQueue类型,该队列用来保存execute方法提交的Runnable任务;*            如果池中没有空闲的线程是,新任务将会保存到这个队列中,等待有空闲的线程后再执行。* threadFactory:线程工厂,用于线程池中创建新线程* handler:如果线程数量已经最大、任务队列已经满了,拒绝新任务的处理策略*/
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,@NotNull java.util.concurrent.TimeUnit unit,@NotNull java.util.concurrent.BlockingQueue<Runnable> workQueue,@NotNull java.util.concurrent.ThreadFactory threadFactory,@NotNull java.util.concurrent.RejectedExecutionHandler handler)

下面我们对workQueue、threadFactory、handler三个参数详细介绍:
    1、workQueue:BlockingQueue类型参数一个阻塞队列,主要用于缓冲任务;

关于阻塞队列可以查看我的另一篇文章:Java阻塞队列—BlockingQueue

2、threadFactory:ThreadFactory类型参数,用来告诉线程池怎么来创建线程
           ThreadFactory接口中定义了方法 Thread newThread(Runnable r);通过实现该接口我们可以定义接口的名称、优先级、是否为守护线程等,我们可以自己实现也可以采用第三方的实现。
           我们参考一下JDK中 Executors类中的DefaultThreadFactory实现,DefaultThreadFactory的源码如下:

static class DefaultThreadFactory implements ThreadFactory {private static final AtomicInteger poolNumber = new AtomicInteger(1);private final ThreadGroup group;private final AtomicInteger threadNumber = new AtomicInteger(1);private final String namePrefix;DefaultThreadFactory() {SecurityManager s = System.getSecurityManager();//设置线程组同当前线程一致group = (s != null) ? s.getThreadGroup() :Thread.currentThread().getThreadGroup();//线程名称前缀namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-";}public Thread newThread(Runnable r) {Thread t = new Thread(group, r,namePrefix + threadNumber.getAndIncrement(),0);//设为非守护线程if (t.isDaemon())t.setDaemon(false);//线程的优先级设为默认的5if (t.getPriority() != Thread.NORM_PRIORITY)t.setPriority(Thread.NORM_PRIORITY);return t;}}

我们使用Executors创建的FixedThreadPool、SingleThreadPool、 CachedThreadPool 和 ScheduledThreadPool就是采用的这个DefaultThreadFactory类。
            我们也可用第三方实现的线程创建工厂,如google的ThreadFactoryBuilder

ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("request-pool-%d").setPriority(1).build();

3、 handler:RejectedExecutionHandler类型参数,线程池拒绝新任务的处理策略
        在ThreadPoolExecutor中有四个RejectedExecutionHandler的实现,分别是:

  • AbortPolicy:丢掉任务,抛出RejectedExecutionException,是线程池的默认策略(jdk代码)
  • DiscardPolicy:直接丢弃,不做任何处理
  • DiscardOldestPolicy:删掉队列头部的任务,再尝试加入队列
  • CallerRunsPolicy:使用主线程执行该任务

ThreadPoolExecutor常用的方法:

    //让线程池执行指定的任务,不一定是立即执行void execute(Runnable command)
    //向线程池中提交指定的任务,如果任务执行成功,则返回的Future对象get得到的将为nullFuture<?> submit(Runnable task)
    //向线程池中提交指定的任务,如果任务执行成功,返回的Future对象get得到的为任务的返回值<T> Future<T> submit(Callable<T> task)
    //向线程池中提交指定的任务,如果任务执行成功,返回的Future对象get得到的就是入参result<T> Future<T> submit(Runnable task, T result)
    //关闭线程池;该方法不会立即终止已经提交的任务,执行该方法后线程池将不再接收新任务,待池中的所有任务执行完成后才会真正的关闭线程池void shutdown()
    //阻塞主线程指定的时间;如果池中任务全部完成返回true阻塞终止,如果超时返回false阻塞终止,主线程如果被中断抛出异常阻塞终止boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException

转载于:https://my.oschina.net/u/2424727/blog/1844593

Java线程池—ThreadPoolExecutor相关推荐

  1. Java线程池ThreadPoolExecutor使用和分析

    Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) Java线程池ThreadPoolExecutor使用和分析(三 ...

  2. java线程池ThreadPoolExecutor类详解

    线程池有哪些状态 1. RUNNING:  接收新的任务,且执行等待队列中的任务 Accept new tasks and process queued tasks  2. SHUTDOWN: 不接收 ...

  3. Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理

    相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...

  4. Java 线程池(ThreadPoolExecutor)原理分析与使用 – 码农网

    线程池的详解 Java 线程池(ThreadPoolExecutor)原理分析与使用 – 码农网 http://www.codeceo.com/article/java-threadpool-exec ...

  5. JAVA线程池ThreadPoolExecutor与阻塞队列BlockingQueue .

    2019独角兽企业重金招聘Python工程师标准>>> 从Java5开始,Java提供了自己的线程池.每次只执行指定数量的线程,java.util.concurrent.Thread ...

  6. java 线程池ThreadPoolExecutor

    线程池 线程池的作用: 线程池作用就是限制系统中执行线程的数量. 根 据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪费了系统资源,多了造成系统拥挤效率不高.用线程池控制线程数 ...

  7. JAVA线程池(ThreadPoolExecutor)源码分析

    JAVA5提供了多种类型的线程池,如果你对这些线程池的特点以及类型不太熟悉或者非常熟悉,请帮忙看看这篇文章(顺便帮忙解决里面存在的问题,谢谢!):     http://xtu-xiaoxin.ite ...

  8. Java 线程池(ThreadPoolExecutor)原理分析与使用

    ThreadPoolExecutor原理概述 在我们的开发中"池"的概念并不罕见,有数据库连接池.线程池.对象池.常量池等等.下面我们主要针对线程池来一步一步揭开线程池的面纱. 使 ...

  9. 转:JAVA线程池ThreadPoolExecutor与阻塞队列BlockingQueue

    从Java5开始,Java提供了自己的线程池.每次只执行指定数量的线程,java.util.concurrent.ThreadPoolExecutor 就是这样的线程池.以下是我的学习过程. 首先是构 ...

  10. Java线程池ThreadPoolExecutor

    2019独角兽企业重金招聘Python工程师标准>>> 本文首发于个人微信公众号<andyqian>, 关注免费获取Java学习资料 前言 多线程一直是Java进阶的必修 ...

最新文章

  1. 简单使用DESeq2/EdgeR做差异分析
  2. java编程思想(第四版)第二章练习题-12
  3. 一个方案提升Flutter内存利用率(干货)
  4. 【招聘(北京武汉)】北京高远华信科技 .NET 高级工程师
  5. HTTPConnectionPool(host:XX)Max retries exceeded with url 解决方法
  6. FFT分析的加窗和重叠
  7. HTML标签之间有什么区别 div 和span?/span
  8. 54扑克牌轮流拿问题,Python实现(详解)
  9. 今日头条自媒体怎么提高推荐量
  10. python编写网页美化_五 使用并美化网页文本
  11. 用于前列腺近距离放疗的MRI / TRUS数据融合初步结果
  12. 验证码输入错误怎么再次刷新验证码
  13. 交换机千兆和百兆对网速影响_千兆网线和百兆网线是否可以通用?
  14. java 取视频第一帧,java获取视频的第一帧
  15. Google pixel Android 8.0 模拟器
  16. 推券客CMS免登陆火车头发布模块
  17. 如何从京东联盟推广链接中解析商品ID
  18. Linux的文件操作2
  19. Android SDK Manager 详细讲解
  20. 【提高组NOIP2017】小凯的疑惑(附证明)

热门文章

  1. ELK-Metricbeat安装及使用
  2. Zabbix 4.0监控PHP-Fpm Pools
  3. Zabbix系统端口监控状态
  4. 未能加载文件或程序集 Newtonsoft.Json, Version=4.5.0.0 的报错,解决方法
  5. 解决Docker安装MySQL不区分大小写问题
  6. Vue---vue-cli 中的proxyTable解决开发环境中的跨域问题
  7. Win10系统如何设置开机启动密码
  8. ros中web端通过 ajax 访问 nginx 加载静态 pgm 地图显示在canvas画布中
  9. 操作SD卡,获取文件目录及文件工具类Android,listView
  10. php+分针和时针重合,关于时针和分钟重合次数的计算