Executors源码学习
时间:2022-07-23
本文章向大家介绍Executors源码学习,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
在学习并发线程池的时候,我们基本都已经学习了一下常见的线程。但是我们发现Executors这样一个类的存在。那么这个类是干什么的?其实在分析ThreadPoolExecutor和ScheledThreadPoolExecutor的时候我们就注意到有一个execute方法了。除此之外还有其他一些方法。当时没有找到是谁在调用。在分析计划任务线程池执行器的时候感觉应该是Executors这个类调用的。那么我们来学习一个Executors究竟是何方圣神吧。
从结构图上看出这个类有一些内部类,显然内部类都是定制的。除此之外此类提供了一些创建线程池的工具类。所以看的出来这块的功能还是类似工具类。
//创建一个固定线程池(最大和核心线程数相同)
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS, LinkedBlockingQueue<Runnable>());
}
//创建一个forkjoin线程池
public static ExecutorService newWorkStealingPool(int parallelism) {
return new ForkJoinPool(parallelism, ForkJoinPool.defaultForkJoinWorkerThreadFactory,null, true);
}
//创建一个forkjoin线程池
public static ExecutorService newWorkStealingPool() {
return new ForkJoinPool(Runtime.getRuntime().availableProcessors(),ForkJoinPool.defaultForkJoinWorkerThreadFactory,null, true);
}
//创建一个固定线程池(核心线程和最大线程相同)
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(),threadFactory);
}
//创建一个单线程的线程池
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>()));
}
//创建一个单线程的线程池
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>(),threadFactory));
}
//创建一个自动增长的线程池
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());
}
//创建一个自动增长的线程池
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(),threadFactory);
}
//创建一个单线程的计划线程池
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1));
}
//创建一个计划线程池
public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory) {
return new DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1, threadFactory));
}
//创建一个计划线程池
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
//创建要给计划线程池
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
//创建一个DelegatedExecutorService
public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
if (executor == null)
throw new NullPointerException();
return new DelegatedExecutorService(executor);
}
//创建一个DelegatedExecutorService
public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
if (executor == null)
throw new NullPointerException();
return new DelegatedScheduledExecutorService(executor);
}
上述方法返回的实体其最终都实现了Executor接口,而Executor接口就只提供了方法execute方法。也就是最终都调用的子类的execute方法。
public interface Executor {
void execute(Runnable command);
}
在现实开发中我们使用比较多的还是ThreadPoolExecutor。但是要注意的是阿里java开发规范中禁止使用Executors方法创建线程。因为除了单线程池和固定线程池外;
Executors创建的线程数量都是采用了Integer.MAX_VALUE;也就是没有做任何限制。
除此之外任务队列均没有限制容量,也就是如果有大量的请求过来就会阻塞到任务队列中。如果数据量比较大的话容易产生OOM问题。
所以我们在创建线程池的时候最好还是手动去创建吧。对于核心线程和最大线程数量都要仔细考虑。除此之外对于线程池的任务队列也要将给个容量。防止堆溢出问题。
- 浅谈Scala在大数据处理方面的优势
- 利用mybatis-generator自动生成代码
- 微信年终放大招!小程序再次升级,这个功能超想要!
- WordPress 中禁止文章自动保存和修订版本的方法
- 第一届机器人学习大会总结
- Hadoop: MapReduce2的几个基本示例
- 使用 nRoute 框架来实现基于 Silverlight 的桌面应用
- oracle:如何用sql生成日历
- 极品双拼“马仔”mazai.com易主终端
- Hadoop:pig 安装及入门示例
- 区块链时代即将到来 它将如何改变我们的工作和生活
- 架设ftp反向代理服务器
- CentOS 7 上面安装PowerShell
- 苹果刻意降低旧 iPhone 效能的做法,或在法国面临刑事检控
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Qt编写安防视频监控系统30-GPS运动轨迹
- Qt编写安防视频监控系统31-onvif设备搜索
- Qt编写安防视频监控系统32-onvif信息获取
- Qt编写安防视频监控系统33-onvif云台控制
- Qt编写安防视频监控系统34-onvif事件订阅
- Qt编写安防视频监控系统35-onvif抓拍图片
- Qt音视频开发1-vlc解码播放
- 【TBase开源版测评】分布式数据自动shard分片
- STL—mt19937
- 潘石屹用Python解决100个问题 | 字符类型统计
- 潘石屹用Python解决100个问题 | 分解质因数
- 使用Java Spring消费MySQL中的数据库存储过程
- 部署 Docker 及配置
- 【Spark on K8S】Spark里的k8s client
- 【每日一题】30. Substring with Concatenation of All Words