Java Executors小结
一
Executors提供了一系列工厂方法用于创先线程池
ThreadPoolExecutor线程池的具体实现类,一般用的各种线程池都是基于这个类实现的
返回的线程池都实现了ExecutorService 接口
二
corePoolSize:线程池的核心线程数,默认情况下可以一直存活。可以通过设置allowCoreThreadTimeOut为True,此时 核心线程数就是0,此时keepAliveTime控制所有线程的超时时间。
maximumPoolSize:线程池允许的最大线程数;
keepAliveTime: 指的是空闲线程结束的超时时间;
unit:是一个枚举,表示 keepAliveTime 的单位;
workQueue:表示存放任务的BlockingQueue
BlockingQueue:是java.util.concurrent下的主要用来控制线程同步的工具。如果BlockQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤醒。同样,如果BlockingQueue是满的,任何试图往里存东西的操作也会被阻断进入等待状态,直到BlockingQueue里有空间才会被唤醒继续操作。BlockingQueue常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。BlockingQueue就是生产者存放元素的容器,而消费者也只从容器里拿元素。
- ArrayBlockingQueue:基于数组、有界,按 FIFO(先进先出)对元素进行排序
- LinkedBlockingQueue:基于链表,按FIFO (先进先出)对元素进行排序
- 吞吐量通常要高于 ArrayBlockingQueue
- FixedThreadPool()SingleThreadExecutor() 使用了这个队列
- SynchronousQueue:不存储元素的阻塞队列
- 每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态
- 吞吐量通常要高于 LinkedBlockingQueue
- CachedThreadPool使用了这个队列
- PriorityBlockingQueue:具有优先级的、无限阻塞队列
DelayedWorkQueue:用于ScheduledThreadPool的添加执行任务,按周期或者延迟执行
threadFactory:每个线程创建的地方 ,可以给线程起个好听的名字,设置个优先级啥的
handler:拒绝策略
- CallerRunsPolicy:只要线程池没关闭,就直接用调用者所在线程来运行任务
- AbortPolicy:直接抛出 RejectedExecutionException 异常
- DiscardPolicy:悄悄把任务放生,不做了
- DiscardOldestPolicy:把队列里待最久的那个任务扔了,然后再调用 execute() 试试看能行不
也可以实现自己的 RejectedExecutionHandler 接口自定义饱和策略
三 线程池分析
FixedThreadPool
- public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
- return new ThreadPoolExecutor(nThreads, nThreads,
- 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>(),
- threadFactory);
- }
FixedThreadPool 的核心线程数和最大线程数都是指定值,也就是说当线程池中的线程数超过核心线程数后,任务都会被放到阻塞队列中。
而这里选用的阻塞队列是 LinkedBlockingQueue,使用的是默认容量 Integer.MAX_VALUE,相当于没有上限。
流程
线程数少于核心线程数,也就是设置的线程数时,新建线程执行任务
线程数等于核心线程数后,将任务加入阻塞队列
由于队列容量非常大,可以一直加加加
执行完任务的线程反复去队列中取任务执行
FixedThreadPool 用于负载比较重的服务器,为了资源的合理利用,需要限制当前线程数量
SingleThreadExecutor
- public static ExecutorService newSingleThreadExecutor() {
- return new FinalizableDelegatedExecutorService
- (new ThreadPoolExecutor(1, 1,
- 0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>()));
- }
从参数可以看出来,SingleThreadExecutor 相当于特殊的 FixedThreadPool,线程1.
流程
线程池中没有线程时,新建一个线程执行任务
有一个线程以后,将任务加入阻塞队列,不停加加加
唯一的这一个线程不停地去队列里取任务执行
SingleThreadExecutor 用于串行执行任务的场景,每个任务必须按顺序执行,不需要并发执行。
CachedThreadPool
- public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
- return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
- 60L, TimeUnit.SECONDS,
- new SynchronousQueue<Runnable>(),
- threadFactory);
- }
CachedThreadPool 没有核心线程,非核心线程数无上限,也就是全部使用外包,但是每个外包空闲的时间只有 60 秒,超过后就会被回收。
CachedThreadPool 使用的队列是 SynchronousQueue,这个队列的作用就是传递任务,并不会保存。
因此当提交任务的速度大于处理任务的速度时,每次提交一个任务,就会创建一个线程。极端情况下会创建过多的线程,耗尽 CPU 和内存资源。
流程
没有核心线程,直接向 SynchronousQueue 中提交任务
如果有空闲线程,就去取出任务执行;如果没有空闲线程,就新建一个
执行完任务的线程有 60 秒生存时间,如果在这个时间内可以接到新任务,就可以继续活下去,否则就销毁
由于空闲 60 秒的线程会被终止,长时间保持空闲的 CachedThreadPool 不会占用任何资源。CachedThreadPool 用于并发执行大量短期的小任务,或者是负载较轻的服务器。
ScheduledThreadPool
- public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
- return new DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1, threadFactory));
- }
ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor, 最多线程数为 Integer.MAX_VALUE ,使用 DelayedWorkQueue 作为任务队列。
ScheduledThreadPoolExecutor 添加任务和执行任务的机制与ThreadPoolExecutor 有所不同。
scheduleAtFixedRate() :按某种速率周期执行
scheduleWithFixedDelay():在某个延迟后执行
四 线程池的关闭
shutdown():不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务
shutdownNow():立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务
Java Executors小结的更多相关文章
- Java中文编码小结
Java中文编码小结 1. 只有 字符到字节 或者 字节到字符 的转换才存在编码转码; 2. Java String 采用 UTF-16 编码方式存储所有字符.unicode体系采用唯一的码点表示唯一 ...
- Java序列化小结
title: Java序列化小结 date: 2017-05-06 20:07:59 tags: 序列化 categories: Java基础 --- Java序列化就是将一个对象转化成一串二进制表示 ...
- [Java并发编程(二)] 线程池 FixedThreadPool、CachedThreadPool、ForkJoinPool?为后台任务选择合适的 Java executors
[Java并发编程(二)] 线程池 FixedThreadPool.CachedThreadPool.ForkJoinPool?为后台任务选择合适的 Java executors ... 摘要 Jav ...
- Java 基础--小结
Java 基础--小结 java基础 Java源程序(.java文件)——>java字节码文件(.class文件)——>由解释执行器(java.exe)将字节码文件加载到java虚拟机( ...
- Java Executors(线程池)
Sun在Java5中,对Java线程的类库做了大量的扩展,其中线程池就是Java5的新特征之一,除了线程池之外,还有很多多线程相关的内容,为多线程的编程带来了极大便利.为了编写高效稳定可靠的多线程程序 ...
- Java多线程小结
简述 Java是支持多线程编程的语言,线程相比于进程更加轻量级,线程共享相同的内存空间,但是拥有独立的栈.减少了进程建立.销毁的资源消耗.jdk1.5后对java的多线程编程提供了更完善的支持,使得j ...
- debian/ubuntu部署java应用小结
近期改的Java应用即将部署,为了强强联合,需要把Java应用部署到linux,我们选择了debian系列.小结一下部署的大致过程,如下: Ubuntu已经默认安装了OpenJDK,但还是比较倾向官方 ...
- 面试贴:java异常小结
java的异常处理在面试中通常是个敏感的话题,这里我从整体框架方面稍微作一下我的小结. java的异常都继承Throwable这个类,也就是都可以抛出来的异常,在这个祖先类下,又分为如下子类: 1.E ...
- 不要使用Java Executors 提供的默认线程池
线程池构造方法 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUni ...
随机推荐
- STM32单片机串口中断+DMA使用(含CUBE配置)
最近又要重新用32做点东西,发现一两年没怎么碰的结果就是,曾经熟得不行的东西都变得极度陌生,这种重新学习记忆的过程过于痛苦,果然还是要留下一些记录给之后失忆的自己的. 1.STM32CUBE配置 1. ...
- python web开发之flask框架学习(2) 加载模版
上次学习了flask的helloword项目的创建,这次来学习flask项目的模版加载: 第一步:创建一个flask项目 第二步:在项目目录的templates文件夹下创建一个html文件 第三步: ...
- AP_MergeSql
) FROM DELTA.PRMCN WHERE ETL_FLAG IN ('A','D')) S; --重跑:删除已跑入数据 DELETE FROM CCRD.PRMCN WHERE JOB_SEQ ...
- 3、OpenCV Python 色彩空间
__author__ = "WSX" import cv2 as cv import numpy as np def color_space( img ): gray_img = ...
- Swift 4.0 正式发布,更快更兼容更好用
Swift4现已正式发布!Swift4在Swift3的基础上,提供了更强大的稳健性和稳定性,为Swift3提供源码兼容性,对标准库进行改进,并添加了归档和序列化等功能. 你可以通过观看WWDC2017 ...
- 小B的询问 莫队分块
题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重 ...
- winfom实现关闭后一直运行
using PLog; using System; using System.Collections.Generic; using System.Diagnostics; using System.L ...
- C语言之对指针概念的初步探究
指针?什么是指针? 指针(pointer)是一个值为内存地址的变量(或数据对象). 接下来从变量的角度分析: 变量有两个属性,一个是地址,一个是值. 指针与普通变量的不同之处在于:指针变量的值是一个内 ...
- C语言中typedef的解释_1
typedef是在计算机编程语言中用来为复杂的声明定义简单的别名,它与宏定义有些差异. 它本身是一种存储类的关键字,与auto.extern.mutable.static.register等关键字不能 ...
- 在Ubuntu中使用AppImage类型文件
右键--属性---权限---允许作为执行文件启动