阿里推荐的线程使用方法 ThreadPoolExecutor
阿里推荐原因:使用线程池可以减少创建和销毁线程上所花的时间以及系统资源的开销,然后之所以不用Executors自定义线程池,用ThreadPoolExecutor是为了规范线程池的使用,还有让其他人更好懂线程池的运行规则。
先说一下关于线程的概念
任务:线程需要执行的代码,也就是Runnable
任务队列:线程满了,就任务就放入任务队列里等待,等其他任务在线程里执行完,这个线程就空出来了,任务队列就将最早来的未执行的任务放入线程执行。
核心线程:线程池一直存在的线程
最大线程数量:指的是线程池所容纳的最多的线程数量
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue)
第一个是核心线程数量,第二个是最大线程数量,第三个是非核心线程的闲置超时时间,超过这个时间就会被回收,第四个是线程池中的任务队列模式。
我们主要讲这个任务队列模式
1.LinkedBlockingDeque
我先上一个例子代码,再来唠嗑
public class MainActivity extends AppCompatActivity {
Button button;
ThreadPoolExecutor executor;
Runnable myRunnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() + " run");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (Button) findViewById(R.id.btn_record_video);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
executor.execute(myRunnable);
executor.execute(myRunnable);
executor.execute(myRunnable);
}
});
executor = new ThreadPoolExecutor(3, 6, 3, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
}
}
当我们点击一次按钮
03-03 15:00:43.503 5292-5333/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:00:43.505 5292-5335/com.example.zth.seven I/System.out: pool-1-thread-3 run
03-03 15:00:43.505 5292-5334/com.example.zth.seven I/System.out: pool-1-thread-2 run
连续点击两次
03-03 15:10:47.941 7114-7259/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:10:47.941 7114-7260/com.example.zth.seven I/System.out: pool-1-thread-2 run
03-03 15:10:47.942 7114-7261/com.example.zth.seven I/System.out: pool-1-thread-3 run
03-03 15:10:49.942 7114-7260/com.example.zth.seven I/System.out: pool-1-thread-2 run
03-03 15:10:49.942 7114-7259/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:10:49.942 7114-7261/com.example.zth.seven I/System.out: pool-1-thread-3 run
这个时候就可以看出虽然说是最大线程数量是6,但是只用核心线程,不创建新线程,如果核心线程用完了就在队列里等待,队列的大小没有限制(你可随便点,他反正后来都会执行)
但是还没完这个LinkedBlockingDeque还可以设置队列数量,如果我把队列设置为2
executor = new ThreadPoolExecutor(3, 6, 3,
TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(2));
然后连续点击2两次
03-03 15:19:39.851 8971-9013/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:19:39.851 8971-9014/com.example.zth.seven I/System.out: pool-1-thread-2 run
03-03 15:19:39.851 8971-9015/com.example.zth.seven I/System.out: pool-1-thread-3 run
03-03 15:19:40.045 8971-9016/com.example.zth.seven I/System.out: pool-1-thread-4 run
03-03 15:19:41.851 8971-9013/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:19:41.851 8971-9015/com.example.zth.seven I/System.out: pool-1-thread-3 run
他这个时候能够创建四个线程了,为何,首先第一次点击占了三个核心线程,然后第二次点击将前两次任务放入队列里,然后队列满了就创建一个新线程用来执行最后一个任务
如果我们连续点击三次,程序在我们点击第三次就崩溃了,因为线程数量超出最大线程数量了
总结:LinkedBlockingDeque就首先使用核心线程,核心线程用完了就把任务放入队列里等待,如果队列满了就创建新线程,注意不设置队列数量,他就默认无限大。
2.SynchronousQueue
我们还是和以前一样换掉一行代码
executor = new ThreadPoolExecutor(3, 6, 3,
TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
点击一次
03-03 15:39:31.915 12403-12446/com.example.zth.seven I/System.out: pool-1-thread-2 run
03-03 15:39:31.915 12403-12447/com.example.zth.seven I/System.out: pool-1-thread-3 run
03-03 15:39:31.915 12403-12445/com.example.zth.seven I/System.out: pool-1-thread-1 run
连续点击两次
03-03 15:39:53.204 12403-12446/com.example.zth.seven I/System.out: pool-1-thread-2 run
03-03 15:39:53.204 12403-12445/com.example.zth.seven I/System.out: pool-1-thread-1 run
03-03 15:39:53.204 12403-12447/com.example.zth.seven I/System.out: pool-1-thread-3 run
03-03 15:39:53.371 12403-12501/com.example.zth.seven I/System.out: pool-1-thread-5 run
03-03 15:39:53.371 12403-12502/com.example.zth.seven I/System.out: pool-1-thread-6 run
03-03 15:39:53.371 12403-12500/com.example.zth.seven I/System.out: pool-1-thread-4 run
可以看出来当核心线程占满时他没有将任务放入队列里去等待,而是直接创建新线程取执行任务
连续点击三次
程序崩溃,因为他创建的线程超过了最大线程数量,
总结:SynchronousQueue很单纯,不使用队列,核心线程用完了就创建新线程,
参考文章:
http://blog.csdn.net/qq_25806863/article/details/71126867
阿里推荐的线程使用方法 ThreadPoolExecutor的更多相关文章
- 从源码看JDK提供的线程池(ThreadPoolExecutor)
一丶什么是线程池 (1)博主在听到线程池三个字的时候第一个想法就是数据库连接池,回忆一下,我们在学JavaWeb的时候怎么理解数据库连接池的,数据库创建连接和关闭连接是一个比较耗费资源的事情,对于那些 ...
- 线程中断方法interrupt() 与 cancel()
(一).关于interrupt() interrupt()并不直接中断线程,而是设定一个中断标识,然后由程序进行中断检查,确定是否中断. 1. sleep() & interr ...
- 线程池之ThreadPoolExecutor详解
为什么要使用线程池 线程是一个操作系统概念.操作系统负责这个线程的创建.挂起.运行.阻塞和终结操作.而操作系统创建线程.切换线程状态.终结线程都要进行CPU调度——这是一个耗费时间和系统资源的事情. ...
- Java并发包线程池之ThreadPoolExecutor
参数详解 ExecutorService的最通用的线程池实现,ThreadPoolExecutor是一个支持通过配置一些参数达到满足不同使用场景的线程池实现,通常通过Executors的工厂方法进行配 ...
- 线程池之 ThreadPoolExecutor
线程池之 ThreadPoolExecutor + 面试题 线程池介绍 线程池(Thread Pool):把一个或多个线程通过统一的方式进行调度和重复使用的技术,避免了因为线程过多而带来使用上的开销. ...
- Android线程管理之ThreadPoolExecutor自定义线程池
前言: 上篇主要介绍了使用线程池的好处以及ExecutorService接口,然后学习了通过Executors工厂类生成满足不同需求的简单线程池,但是有时候我们需要相对复杂的线程池的时候就需要我们自己 ...
- 线程池:ThreadPoolExecutor
[ThreadPoolExecutor的使用和思考] public ThreadPoolExecutor(int corePoolSize, ...
- 从源码解读线程(Thread)和线程池(ThreadPoolExecutor)的状态
线程是比进程更加轻量级的调度执行单位,理解线程是理解并发编程的不可或缺的一部分:而生产过程中不可能永远使用裸线程,需要线程池技术,线程池是管理和调度线程的资源池.因为前不久遇到了一个关于线程状态的问题 ...
- Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析
目录 引出线程池 Executor框架 ThreadPoolExecutor详解 构造函数 重要的变量 线程池执行流程 任务队列workQueue 任务拒绝策略 线程池的关闭 ThreadPoolEx ...
随机推荐
- CentOS 7安装mysql(rpm)
1.检查是否安装了mysql rpm -qa|grep -i mysql centos7默认是安装的mariadb,而安装mysql的话会和mariadb的文件冲突,所以需要先卸载掉mariadb 2 ...
- BZOJ 4195: [Noi2015]程序自动分析 并查集+离散化
LUOGU 1955BZOJ 4195 题目描述 在实现程序自动分析的过程中,常常需要判定一些约束条件是否能被同时满足. 考虑一个约束满足问题的简化版本:假设x1,x2,x3...代表程序中出现的变量 ...
- Python3 tkinter基础 Radiobutton variable 默认选中的按钮
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- BTrace:线上问题排查工具
BTrace简介 GitHub地址:BTrace 下载地址:v1.3.11.3 官方使用教程:Btrace使用教程 使用场景 BTrace 是一个事后工具,所谓事后工具就是在服务已经上线了,但是发现存 ...
- 最简单获取appPackage和appActivity 的方法
appPackage和appActivity 进行appium自动化测试必须的两个参数,我们所测试的APP项目不同,这两个参数肯定也是不一样的.我们启动的包都是靠这两个参数去驱动的,那么我们怎么可以快 ...
- Kde桌面的Mac化
KDE->Mac \(Mac\) 的审美可以说是很成熟了,确实让人很喜欢啊!于是不由得想弄一个 \(Mac\) 风的桌面. 先放张图吧: 效果还蛮不错的哇. \(Mac\) 原生的壁纸下载链接: ...
- 11_vim
vim编辑器 文本编辑器,字处理器linux重要哲学思想之一:使用纯文本格式来保存软件的配置信息,大多数情况下都是如此,而且一切皆文件此前学过nano,sed..nano入门简单,但功能简陋 vi:V ...
- mitmproxy(中间人攻击工具)安装及使用
一.安装 执行命令,报错 pip install mitmproxy 根据提示安装vc++14后重新执行正常安装. 查看版本号: mitmproxy --version Error: mitmprox ...
- kali linux 使用笔记本快捷键调节音量
环境:kali 2018.3a(xface桌面版),自带PulseAudio控制音量. 以前在windows时笔记本是Fn+F1这些来调节音量的,装了kali后原来调节亮度.触控板的键还能用,唯独音量 ...
- vue入门练习(一)
1.安装node,webpack node -v //查看已安装版本 npm install -g webpack //安装webpack npm install -g webpack-dev-se ...