当前位置: 首页 > news >正文

线程精进指南之线程池进阶

为什么引进线程池
鱼池,我们可以钓出来一条再放回去,钓出来一条再放回去,这样来撩鱼。
那线程池该如何玩呢?对,取出来一“条”线程,用完后再扔回去,再取出来,再扔....
线程池的优点:
避免大量的创建和销毁带来的性能开销
避免大量的线程间因互相抢占系统资源导致的阻塞现象。
能够对线程进行简单的管理并提供定时执行、间隔执行等功能。
缺点
占用一定的内存空间。
线程越多CPU的调度开销越大。
程序的复杂度会上升。
线程池的基本使用
使用线程池 ,肯定要对“池”进行配置,像基本的池多大啊,能容纳多少鱼啊,等这些是需要建造前就要确定的,因此我们搞池之前先设计
•int corePoolSize 核心线程最大数
无论是闲置还是工作中,永远都不会销毁的线程,会一直在线程池中存在,那我们是不是永远都奈何不了它呢,当然不会,把ThreadPoolExecutor的allowCoreThreadTimeOut这个属性设置为true,超过规定时长也会销毁
•int maximumPoolSize 线程总数最大值
就是我们所有的线程啊,对,包括非核心的和上边讲的核心的
•long keepAliveTime
如果不是核心线程,超过这个参数的时间就会被干掉
•TimeUnit unit
时间总是有单位的吧,对就是上边KeepAliveTime的时间参数哇
类型时枚举,这里举几种常用的,反正说多了也记不住,需要时候IDEA会提示
SECONDS : 秒
MINUTES : 分
HOURS : 小时
DAYS : 天
•BlockingQueue workQueue
队列内容较多,我们下边单独讲
•ThreadFactory threadFactory

这个一般不用,没必要管啦
•RejectedExecutionHandler handler
如果执行的过程中,抛异常了,我们可以用这个来指定,但是系统有默认的,因此这个也可以不用

使用线程池当然离不开Executor这个接口,具体的实现类在ThreadPoolExecutor中,so我们简单了解下这个类
//对,使用的就是这几个构造,参数我们上边已经将过了
public class ThreadPoolExecutor extends AbstractExecutorService {
.....
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue);

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory);

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler);

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler);
...

}

常用的几种线程池
线程都池都是是使用Executors这个类创建出来的
•CachedThreadPool()
可缓存线程池:
线程数无限制
优先使用空闲线程,如果没有才新建线程
//创建方式
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

//源码中的定义
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

•FixedThreadPool()
固定长度的线程池
可以控制线程的数量
如果超过则必须排队执行
//创建方式
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(线程数量);

//源码中的定义
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
•ScheduledThreadPool()
对,就是它可以定时
//创建方法
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(最大线程数);

//源码中的定义
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}
•SingleThreadExecutor()
所有任务排队执行,一次只能执行一个任务
//创建方法
ExecutorService singleThreadPool = Executors.newSingleThreadPool();

//源码中的定义
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
队列
队列类似我们的集合,实现了Collection接口
队列中排队执行的是我们runnable对象
常用的队列有如下几种
•SynchronousQueue:
有任务来就执行交给空闲线程,如果没有就新建线程执行,so 线程数设置尽可能大即Integer.MAX_VALUE
•LinkedBlockingQueue:
永远在核心线程内使用线程,如果超过了核心的线程就在队列中等待执行
•ArrayBlockingQueue:
优先使用核心线程数,其次使用非核心的,如果用完了就进入队列等待
•DelayQueue:
想进入队列必须实现Delayed接口,达到指定时间后,方可执行任务

读书百遍不如代码十遍,提升的唯一道路唯有你的手速!

转载于:https://blog.51cto.com/13517854/2052064

相关文章:

  • ifdef ANDROID总是不好用
  • 如何阅读slow日志
  • 11.18 Apache用户认证
  • Shell的 for 循环小例子
  • iOS10 之前键盘跳转到设置页面的 url
  • ORA-01012: not logged on
  • MySQL GEO 字段类型说明及案例
  • iOS推送机制APNs
  • OSChina 周六乱弹 ——薯哥,你冷静,巴叔是你弟弟啊!
  • [转]如何写出线程安全的类和函数
  • [svc]logstash和filebeat之间ssl加密
  • 将手机替换为*号
  • python入门之路 一
  • 网络数据抓取
  • Xcode 7 制作 framework
  • [ JavaScript ] 数据结构与算法 —— 链表
  • AWS实战 - 利用IAM对S3做访问控制
  • Git的一些常用操作
  • JavaScript服务器推送技术之 WebSocket
  • Java读取Properties文件的六种方法
  • Koa2 之文件上传下载
  • Python - 闭包Closure
  • 大型网站性能监测、分析与优化常见问题QA
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 构建二叉树进行数值数组的去重及优化
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 项目管理碎碎念系列之一:干系人管理
  • 选择阿里云数据库HBase版十大理由
  • ​马来语翻译中文去哪比较好?
  • ​虚拟化系列介绍(十)
  • #android不同版本废弃api,新api。
  • #我与Java虚拟机的故事#连载02:“小蓝”陪伴的日日夜夜
  • #在 README.md 中生成项目目录结构
  • (007)XHTML文档之标题——h1~h6
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (转)一些感悟
  • .NET Core6.0 MVC+layui+SqlSugar 简单增删改查
  • .NET Framework 4.6.2改进了WPF和安全性
  • .Net下的签名与混淆
  • [APIO2012] 派遣 dispatching
  • [C#小技巧]如何捕捉上升沿和下降沿
  • [EFI]ASUS EX-B365M-V5 Gold G5400 CPU电脑 Hackintosh 黑苹果引导文件
  • [Enterprise Library]调用Enterprise Library时出现的错误事件之关闭办法
  • [Foreman]解决Unable to find internal system admin account
  • [hdu1561] The more, The Better 【树形DP】
  • [LeetCode]-Spiral Matrix III 螺旋矩阵
  • [ndss 2023]确保联邦敏感主题分类免受中毒攻击
  • [Oh My C++ Diary]带参数的main()函数
  • [POJ 2406]Power Strings[KMP]
  • [StartingPoint][Tier0]Synced
  • [ThinkPHP]Arr返回1
  • [UGUI]实现从一个道具栏拖拽一个UI道具到另一个道具栏
  • [毕业生的商业软件开发之路]C#可访问级别
  • [编程题]抄送列表 - 牛客网题解
  • [创建和构建应用程序的主要工具] 之 javac