线程池ThreadPoolExecutor的使用方法
方法我们通过继承Thread类和实现runnable接口或者callable接口三种方式实现。
继承Thread类实际上也是实现了runnable接口,被继承的类主要是实现run()方法,通过start()方法调用。
而callable接口是属于Executor
对比与Runnable接口功能的区别是:
(1).Callable可以在任务结束后提供一个返回值,Runnable没有这个功能
(2).Callable中的call()方法可以抛出异常,而Runnable的run()方法不能抛出异常
(3).运行Callable可以拿到一个Future对象,Future独享表示异步计算的结果,它提供了检查计算是否完成的方法。由于线程属于异步计算模型,因此无法从别的线程中得到函数
的返回值,在这种情况下,就可以使用Future来监视目标线程调用call()方法的情况,放调用Future的get()方法以获取结果时,当前线程就会阻塞,知道call()方法结束返回结果。 我们可以使用多线程来达到最优效率,但是,线程不是越多就越好,线程过多,创建和销毁就会消耗系统的资源,也不方便管理。
除此之外,多线程还会造成并发问题,线程并发数量过多,抢占系统资源从而导致阻塞。
我们将线程放入线程池,由线程池对线程进行管理,可以对线程池中缓冲的线程进行复用,这样,就不会经常去创建和销毁线程了,从而省下了系统的资源。
线程池能够有效的控制线程并发的数量,能够解决多线程造成的并发问题。
ThreadPoolExecutor
Java提供了ThreadPoolExecutor线程池类,他的构造方法有四个,主要是参数不同




corePoolSize为的线程池最大核心线程数量
maximumPoolSize为最大线程池数量
keepAliveTime 当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间
unit 存活时间的单位
workQueue 存放线程的工作队列
handler:超出线程范围和队列容量的任务的处理程序(拒绝策略)
当线程放入线程池中,当线程的数量已经等于最大的核心线程数量,此线程就会放入线程队列当中,等待线程的调用。
线程池的最大线程数(线程总数,maximumPoolSize)= 核心线程数(corePoolSize)+非核心线程数
核心线程是永远不会被线程池丢弃回收(即使核心线程没有工作),非核心线程则是超过一定时间(keepAliverTime)则就会被丢弃
Excutors工具类
java提供了Excutors工具类,适用于一下小项目,对于一些大型程序还是需要自己创建ThreadPoolExecutor类,因为Excutors可能会造成OOM(堆内存溢出)
FixedThreadPool 和 SingleThreadExecutor : 允许请求的队列长度为 Integer.MAX_VALUE,可能堆积大量的请求,从而导致OOM。
CachedThreadPool 和 ScheduledThreadPool : 允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致OOM。
| 方法 | 说明 |
| newFixedThreadPool(int nThreads) | 创建固定大小的线程池 |
| newSingleThreadExecutor() | 创建只有一个线程的线程池 |
| newCachedThreadPool() | 创建一个不限线程数上限的线程池,任何提交的任务都将立即执行 |
| newScheduledThreadPool(int nThreads) | 创建一个支持定时、周期性或延时任务的限定线程数目的线程池 |
| newSingleThreadScheduledExecutor() | 创建一个支持定时、周期性或延时任务的单个线程的线程池 |
线程池获取执行结果
把线程提交给线程池中,有两种方法,一种是submit,另外一种则是execute
execute没有返回值,性能会好很多,submit返回一个Future对象,如果想知道线程结果就使用submit提交,而且它能在主线程中通过Future的get方法捕获线程中的异常。
这两种方法的参数必须要实现runnable接口或者是callable对象
线程池的处理结果、以及处理过程中的异常都被包装到Future中,并在调用Future.get()方法时获取,执行过程中的异常会被包装成ExecutionException。
关闭线程池
可以通过shutdown()或者shutdownNow()方法
shutdown() : 不再接受新的任务,之前提交的任务等执行结束再关闭线程池
shutdownNow() :不再接受新的任务,试图停止池中的任务再关闭线程池,返回所有未处理的线程list列表。
Semaphore 的使用方式
Semaphore 是 synchronized 的加强版,作用是控制线程的并发数量。(并发控制信号量)
我们可以在主要执行任务的call()方法或者run()方法中使用semaphore来控制并发。
semaphore的构造方法有两个

第一个构造方法的参数为同一时刻允许线程进入的个数,如果为1,就相当于单个线程。
第二个构造方法的参数为线程公平性isFair
isFair 的意思就是,是否公平,获得锁的顺序与线程启动顺序有关,就是公平,先启动的线程,先获得锁。isFair 不能100% 保证公平,只能是大概率公平。
isFair 为 true,则表示公平,先启动的线程先获得锁。

在 semaphore.acquire() 和 semaphore.release()之间的代码,同一时刻只允许制定个数的线程进入, 因为semaphore的构造方法是1,则同一时刻只允许一个线程进入,其他线程只能等待。
acquire:
线程池ThreadPoolExecutor的使用方法的更多相关文章
- [3]java1.8线程池—ThreadPoolExecutor
Wiki 上是这样解释的:Thread Pool 作用:利用线程池可以大大减少在创建和销毁线程上所花的时间以及系统资源的开销! 下面主要讲下线程池中最重要的一个类 ThreadPoolExecutor ...
- 线程池ThreadPoolExecutor的学习
我们知道,ExecutorService是一个抽象出线程池的一个接口,然后我们在使用线程池的时候,用的是Executors工具类中的一系列newCachedThreadPool() 等类似的方法,这些 ...
- 硬核干货:4W字从源码上分析JUC线程池ThreadPoolExecutor的实现原理
前提 很早之前就打算看一次JUC线程池ThreadPoolExecutor的源码实现,由于近段时间比较忙,一直没有时间整理出源码分析的文章.之前在分析扩展线程池实现可回调的Future时候曾经提到并发 ...
- 12.ThreadPoolExecutor线程池原理及其execute方法
jdk1.7.0_79 对于线程池大部分人可能会用,也知道为什么用.无非就是任务需要异步执行,再者就是线程需要统一管理起来.对于从线程池中获取线程,大部分人可能只知道,我现在需要一个线程来执行一个任 ...
- java 线程池ThreadPoolExecutor 如何与 AsyncTask() 组合使用。
转载请声明出处谢谢!http://www.cnblogs.com/linguanh/ 这里主要使用Executors中的4种静态创建线程池实例方法中的 newFixedThreadPool()来举例讲 ...
- java线程池ThreadPoolExecutor使用简介
一.简介线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize, int m ...
- java线程池ThreadPoolExecutor理解
Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixe ...
- 线程池ThreadPoolExecutor、Executors参数详解与源代码分析
欢迎探讨,如有错误敬请指正 如需转载,请注明出处 http://www.cnblogs.com/nullzx/ 1. ThreadPoolExecutor数据成员 Private final Atom ...
- 线程池ThreadPoolExecutor
线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为: ThreadPoolExecutor(int corePoolSize, int maxi ...
随机推荐
- 4. SOFAJRaft源码分析— RheaKV初始化做了什么?
前言 由于RheaKV要讲起来篇幅比较长,所以这里分成几个章节来讲,这一章讲一讲RheaKV初始化做了什么? 我们先来给个例子,我们从例子来讲: public static void main(fin ...
- CMMS系统中工单派案&调度
系统为客户经理提供一个有效的调度控制台,由客户经理负责将需要外派现场处理的工单进行统一的分配调度,系统显示每个技术人员的时间表,根据专业技能.可用性.距离或其他资格标准筛选技术服务人员,并向调度人员提 ...
- Mysql UTF-8mb4字符集的问题
官方Mysql手册链接 https://dev.mysql.com/doc/connectors/en/connector-j-reference-charsets.html Notes For Co ...
- Java基础(十一)回调(callback)与对象克隆(Cloneable)
一.回调 1.回调是一种常见的程序设计模式,可以指出某个特定时间发生时应该采取的动作. 在java.swing包中有一个类Timer类,可以使用它在到达指定的时间间隔作出什么动作.那么就有两个问题,即 ...
- 四元数(Quaternion)
从应用角度说一下unity Quaternion,Quaternion是四元数,百度相关资料可能找到的都是一些大牛给你搞个矩阵云云,给你讲解四元数.在此只是从应用角度讲一讲.最简单理解四元数对应一个向 ...
- MacOS 系统 文件夹解析
Mac OS X,基于UNIX核心的系统,增强了系统的稳定性.性能以及响应能力. 通过对称多处理技术充分发挥双处理器的优势,提供无与伦比的2D.3D和多媒体图形性能以及广泛的字体支持和集成的PDA功能 ...
- shell 脚本中的注释详解
上次写了shell脚本的注释,没想到那么多人的需要,也存在不少不足.这次做个补充吧. 单行注释: 单行注释就比较简单了,直接在行最前端加上符号 # 即可.具体用法如下所示: # this is com ...
- st表、树状数组与线段树 笔记与思路整理
已更新(2/3):st表.树状数组 st表.树状数组与线段树是三种比较高级的数据结构,大多数操作时间复杂度为O(log n),用来处理一些RMQ问题或类似的数列区间处理问题. 一.ST表(Sparse ...
- Alibaba Java Coding Guidelines,以后的Java代码规范,就靠它了
前言 对于Java代码规范,业界有统一的标准,不少公司对此都有一定的要求.但是即便如此,庞大的Java使用者由于经验很水平的限制,未必有规范编码的意识,而且即便经验丰富的老Java程序员也无法做到时刻 ...
- [2018-01-12] laravel--路由(路由与控制器)
路由只用来接收请求 目前我们大致了解了laravel,在开始一个Http程序需要先定义路由.之前的例子中,我们的业务逻辑都是在路由里实现的,这对于简单的网站或web应用没什么问题,当我们需要扩大规模, ...