java - jdk线程池详解
线程池参数详解
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
| 参数 | 说明 |
|---|---|
| corePoolSize | 表示常驻核心线程数量。 |
| maximumPoolSize | 表示线程池中能同时执行的最大线程数量。这个值必须大于等于corePoolSize,如果这两个值相等,那就是固定大小的线程池。 |
| keepAliveTime | 表示线程池中除常驻核心线程之外的其他线程的空闲时间,如果超过这个时间就会销毁。 |
| unit | keepAliveTime的单位。 |
| workQueue | 任务队列,被提交但尚未被执行的任务。 |
| threadFactory | 表示生成线程池中工作线程的线程工厂。 |
| handler | 拒绝策略,表示当队列满了且工作线程大于等于线程池的最大线程数该采用什样的拒绝策略。 |
| 拒绝策略 | 说明 |
|---|---|
| AbortPolicy(默认) | 直接抛出RejectedExecutionException异常阻止系统正常运行。 |
| CallerRunsPolicy | "调用者运行"一种调节机制,该策略即不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者的线程去执行。 |
| DiscardOldestPolicy | 抛弃队列中等待最久的任务,然后把当前任务加入队列中尝试再次提交当前任务。 |
| DiscardPolicy | 直接丢弃任务,不予任务处理也不抛出异常。如果允许任务丢失,这是最好的一种方案。 |
jdk内置的线程池
- Executors.newFixedThreadPool(int)
- Executors.newSingleThreadExecutor()
- Executors.newCachedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
在newFixedThreadPool和newSingleThreadExecutor中阻塞队列均采用默认的LinkedBlockingQueue导致这个阻塞队列的长度达到Integer.MAX_VALUE,当某一时刻有大量的任务涌入线程池中容易导致JVM发生OOM问题
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
而在newCachedThreadPool中采用的是SynchronousQueue这种阻塞队列,该队列任意时刻最多只能有一个元素并且一个put操作必须等待另一个take操作完成。它并不是一个容器,可以认为它是一个快速交换信息的通道。虽然该队列对外的size为0,但由于该线程池的定义maximumPoolSize为Integer.MAX_VALUE,当有大量任务涌入时则会创建出大量的线程Thread对象导致OOM等问题。
虽然在JDK中内置了已经定义好的线程池但是在生产环境下应该尽量使用自己自定义的线程池
线程池执行流程
- 在创建了线程池后,等待提交过来的任务请求。
- 当调用execute()方法添加一个请求任务时,线程池会做如下判断。
2.1 如果正在运行的线程数量小于corePoolSize,那么马上创建线程运行这个任务。
2.2 如果正在运行的线程数量大于或等于corePoolSize,那么将这个任务加入队列。
2.3 如果这时候队列满了且正在运行的线程数量还小于maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务。
2.4 如果队列满了且正在运行的线程数量大于或等于maximumPoolSize,那么线程池会启动饱和拒绝策略来执行。 - 当一个线程完成任务时,它会从队列中取下一个任务来执行。
- 当一个线程无事可做超过一定的时间(keepAliveTime)时,线程池会判断:如果当前运行的线程数大于corePoolSize,那么这个线程就会被停掉。
注意:LinkedBlockingQueue是一个无界(界限为Integer.MAX_VALUE)缓存等待队列。当前执行的线程数量达到corePoolSize的数量时,剩余的元素会在阻塞队列里等待。(所以在使用此阻塞队列时maximumPoolSizes就相当于无效了)。
线程数的选择
CPU密集型任务配置尽可能少的线程数量:
一般公式:CPU核数+1个线程的线程池
由于IO密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程,如CPU核数*2
IO密集型,即该任务需要大量的IO,即大量的阻塞。
在单线程上运行IO密集型的任务会导致浪费大量的CPU运算能力浪费在等待。
所以在IO密集型任务中使用多线程可以大大的加速程序运行,即使在单核CPU上,这种加速主要就是利用了被浪费掉的阻塞时间。
IO密集型时,大部分线程都阻塞,故需要多配置线程数:
参考公式:CPU核数/(1-阻塞系统) 阻塞系数在0.8~0.9之间
比如8核CPU:8/(1-0.9)=80个线程数
java - jdk线程池详解的更多相关文章
- Java多线程-----线程池详解
1. 线程池的实现原理 提交一个任务到线程池中,线程池的处理流程如下: 判断线程池里的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务.如果 ...
- java/android线程池详解
一,简述线程池: 线程池是如何工作的:一系列任务出现后,根据自己的线程池安排任务进行. 如图: 线程池的好处: 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销. 能有效控制线程池的最大并 ...
- Java线程池详解(二)
一.前言 在总结了线程池的一些原理及实现细节之后,产出了一篇文章:Java线程池详解(一),后面的(一)是在本文出现之后加上的,而本文就成了(二).因为在写完第一篇关于java线程池的文章之后,越发觉 ...
- 三、VIP课程:并发编程专题->01-并发编程之Executor线程池详解
01-并发编程之Executor线程池详解 线程:什么是线程&多线程 线程:线程是进程的一个实体,是 CPU 调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系 ...
- nginx源码分析线程池详解
nginx源码分析线程池详解 一.前言 nginx是采用多进程模型,master和worker之间主要通过pipe管道的方式进行通信,多进程的优势就在于各个进程互不影响.但是经常会有人问道,n ...
- Java 并发编程 | 线程池详解
原文: https://chenmingyu.top/concurrent-threadpool/ 线程池 线程池用来处理异步任务或者并发执行的任务 优点: 重复利用已创建的线程,减少创建和销毁线程造 ...
- Java线程池详解
一.线程池初探 所谓线程池,就是将多个线程放在一个池子里面(所谓池化技术),然后需要线程的时候不是创建一个线程,而是从线程池里面获取一个可用的线程,然后执行我们的任务.线程池的关键在于它为我们管理了多 ...
- Java多线程之线程池详解
前言 在认识线程池之前,我们需要使用线程就去创建一个线程,但是我们会发现有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因 ...
- Java线程池详解(一)
一.线程池初探 所谓线程池,就是将多个线程放在一个池子里面(所谓池化技术),然后需要线程的时候不是创建一个线程,而是从线程池里面获取一个可用的线程,然后执行我们的任务.线程池的关键在于它为我们管理了多 ...
随机推荐
- [MacOS-Memcached]安装
查看memcached信息 $ brew info memcached memcached: stable 1.5.22 (bottled), HEAD High performance, distr ...
- 3.【Spring Cloud Alibaba】声明式HTTP客户端-Feign
使用Feign实现远程HTTP调用 什么是Feign Feign是Netflix开源的声明式HTTP客户端 GitHub地址:https://github.com/openfeign/feign 实现 ...
- Http2优点
1.信道复用 2.分帧传输 3.Server Push Http/1.1与Http/2对比网站: https://http2.akamai.com/demo https://http2.akamai. ...
- 面试突击 | Redis 如何从海量数据中查询出某一个 Key?附视频
1 考察知识点 本题考察的知识点有以下几个: Keys 和 Scan 的区别 Keys 查询的缺点 Scan 如何使用? Scan 查询的特点 2 解答思路 Keys 查询存在的问题 Scan 的使用 ...
- MySQL基础(4) | 视图
MySQL基础(4) | 视图 基本语法 1.创建 CREATE VIEW <视图名> AS <SELECT语句> 语法说明如下. <视图名>:指定视图的名称.该名 ...
- windows7精简iso
网站地址: https://www.90pan.com/b1268487 迅雷链接: magnet:?xt=urn:btih:EE4B0FE780B6EC97D6FB9A9D22A8EE1627DA7 ...
- C#中StreamReader类读取文件使用示例
C#中StreamReader类读取文件使用示例 1.需要导入的命名空间是:System.IO; 2.操作的是字符,所以打开的是文本文件. 常用属性: CurrentEncoding:对象正在使用 ...
- TCP/IP详解阅读记录----第二章 数据链路层
1.以太网 以太网是当今TCP/IP采用的主要的局域网技术.它采用一种称作CSMA/CD的媒体接入方法,其意思是带冲突检测的载波侦听多路接入.它的速率为10Mb/s,地址为48bit. 2.I ...
- 简单配置让iterm2用得更爽
同步自本人独立博客:https://liushiming.cn/2020/01/15/awesome-iterm2-config/ 概述 iterm2比mac原生的terminal好用很多,是mac下 ...
- Arduino 制作截图区域