线程池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 ...
随机推荐
- 二叉树的查找(前序、中序、后序、层序遍历)--biaobiao88
建立一棵含有n个结点的二叉树,采用二叉链表存储: 输出前序.中序.后序..层序遍历该二叉树的遍历结果. 定义二叉树的数据类型——二叉树结点结构体BiNode.建立二叉链表可以采用扩展二叉树的一个遍历序 ...
- task一个任务结束后执行另一个操作
//创建一个任务 Task<int> task = new Task<int>(() => { ; //显示进度条遮照层, this.ShowPrograssBar(); ...
- Java多线程编程(七)线程状态、线程组与异常处理
一.线程的状态 线程对象在不同的运行时期有不同的状态,状态信息就存在于State枚举类中. 调用与线程有关的方法后,会进入不同的线程状态,这些状态之间某些是可双向切换的,比如WAITING和RUNNI ...
- TCP UDP基本编程(一)
tcp udp均可以用来网络通信,在使用之前建议先搜索一下相关网络连接的基本知识,可以更好的理解和使用,tcp建议看下如下文章:https://blog.csdn.net/chuangsun/arti ...
- GO基础之List
一.List定义 概述1.list是一种非连续存储的容器,由多个节点组成,节点通过一些变量记录彼此之间的关系.list有多种实现方法,如单向链表.双向链表等.2.Go语言中list的实现原理是双向链表 ...
- 数据后台管理(五)AOP日志
为了增加数据的安全性,在数据管理的过程中,我们需要将操作者访问时间,操作者的名称,访问的IP,访问资源的URL,执行时长,访问方法记录下来存储到数据库中,并可以通过页面查看. 1.将日志信息存储到数据 ...
- [翻译]——MySQL 8.0 Histograms
前言: 本文是对这篇博客MySQL 8.0 Histograms的翻译,翻译如有不当的地方,敬请谅解,请尊重原创和翻译劳动成果,转载的时候请注明出处.谢谢! 英文原文地址:https://lefred ...
- 面试精选:JVM垃圾回收
Tips:关注公众号:松花皮蛋的黑板报,领取程序员月薪25K+秘籍,进军BAT必备! Java堆中存放着大量的Java对象实例,在垃圾收集器回收内存前,第一件事情就是确定哪些对象是“活着的”,哪些是可 ...
- ElasticSearch(一):基本概念
ElasticSearch(一):基本概念 学习课程链接<Elasticsearch核心技术与实战> 基本概念示意图 索引与文档更偏向于开发人员的视角,属于逻辑上的一种概念:节点与分片更偏 ...
- NFS共享目录
NFS(Network Files System)即网络文件系统 NFS文件系统协议允许网络中的主机通过TCP/IP协议进行资源共享,NFS客户端可以像使用本地资源一样读写远端NFS服务端的资料,需要 ...