博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java线程池理论知识拾遗
阅读量:4295 次
发布时间:2019-05-27

本文共 1960 字,大约阅读时间需要 6 分钟。

五种线程池的使用场景

newSingleThreadExecutor:一个单线程的线程池,可以用于需要保证顺序执行的场景,并且只有一个线程在执行。

newFixedThreadPool:一个固定大小的线程池,可以用于已知并发压力的情况下,对线程数做限制。

newCachedThreadPool:一个可以无限扩大的线程池,比较适合处理执行时间比较小的任务。

newScheduledThreadPool:可以延时启动,定时启动的线程池,适用于需要多个后台线程执行周期任务的场景。

newWorkStealingPool:一个拥有多个任务队列的线程池,可以减少连接数,创建当前可用cpu数量的线程来并行执行。

线程池的关闭

关闭线程池可以调用shutdownNow和shutdown两个方法来实现

shutdownNow:对正在执行的任务全部发出interrupt(),停止执行,对还未开始执行的任务全部取消,并且返回还没开始的任务列表。

shutdown:当我们调用shutdown后,线程池将不再接受新的任务,但也不会去强制终止已经提交或者正在执行中的任务。

初始化线程池时线程数的选择

如果任务是IO密集型,一般线程数需要设置2倍CPU数以上,以此来尽量利用CPU资源。

如果任务是CPU密集型,一般线程数量只需要设置CPU数加1即可,更多的线程数也只能增加上下文切换,不能增加CPU利用率。

上述只是一个基本思想,如果真的需要精确的控制,还是需要上线以后观察线程池中线程数量跟队列的情况来定。

线程池都有哪几种工作队列

1、ArrayBlockingQueue

是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。

2、LinkedBlockingQueue

一个基于链表结构的无界阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列

3、SynchronousQueue

一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。

4、PriorityBlockingQueue

一个具有优先级的无限阻塞队列。

线程池的拒绝策略

当请求任务不断的过来,而系统此时又处理不过来的时候,我们需要采取的策略是拒绝服务。RejectedExecutionHandler接口提供了拒绝任务处理的自定义方法的机会。在ThreadPoolExecutor中已经包含四种处理策略。

  • AbortPolicy策略:该策略会直接抛出异常,阻止系统正常工作。

  • CallerRunsPolicy 策略:只要线程池未关闭,该策略直接在调用者线程中,运行当前的被丢弃的任务。

  • DiscardOleddestPolicy策略: 该策略将丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务。

  • DiscardPolicy策略:该策略默默的丢弃无法处理的任务,不予任何处理。

    除了JDK默认提供的四种拒绝策略,我们可以根据自己的业务需求去自定义拒绝策略,自定义的方式很简单,直接实现RejectedExecutionHandler接口即可。

poolSize

  • corePoolSize和maximumPoolSize

    当在方法execute中提交一个新任务,并且运行的线程小于corePoolSize时,即使其他工作线程处于空闲状态,也将创建一个新线程来处理请求新的任务,核心线程都创建后,新的任务将丢到队列里面,由线程获取执行。如果有超过corePoolSize但小于maximumPoolSize的线程在运行,则只有在工作队列已满时才会创建新线程。通过将corePoolSize和maximumPoolSize设置为相同达到创建一个固定大小的线程池。通过将maximumPoolSize设置为一个没有上限的值,例如Integer.MAX_VALUE,则允许池容纳任意数量的并发任务。corePoolSize和maximumPoolSize仅在构建时设置,但也可以使用setCorePoolSize和setMaximumPoolSize动态更改它们;

  • 默认情况下,即使是核心线程也只是在新任务到达时才被创建和启动,但是可以使用方法prestartCoreThread或prestartAllCoreThreads动态地覆盖这一点,如果使用非空队列构造池,则可能需要预启动线程。

转载地址:http://cebws.baihongyu.com/

你可能感兴趣的文章
Makefile教程
查看>>
arm-none-eabi交叉编译工具常用的一些指令
查看>>
Ubuntu 常用解压与压缩命令
查看>>
C语言结构体指针变量作函数参数
查看>>
C语言动态存储分配
查看>>
文科生清晰理解傅里叶变换
查看>>
C++数据类型
查看>>
C语言整型数据(整数)
查看>>
C语言常量与变量
查看>>
C语言实型数据(浮点数)
查看>>
C语言数据类型转换
查看>>
C语言指针变量作为函数参数
查看>>
C语言局部变量和全局变量
查看>>
C语言变量的存储类别
查看>>
C语言结构体指针变量作函数参数
查看>>
C语言动态存储分配
查看>>
MSP430中断原理分析
查看>>
display几点解释
查看>>
详解SPI中的极性CPOL和相位CPHA
查看>>
各类总线传输速率
查看>>