首页 > 其他分享 >还不知道线程池的好处?快来了解一下

还不知道线程池的好处?快来了解一下

时间:2023-03-01 15:31:58浏览次数:50  
标签:处理 队列 好处 任务 了解 线程 workQueue 执行

摘要:线程池的好处:重用存在的线程,减少对象创建、消亡的开销,性能佳;可以有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞。

本文分享自华为云社区《​​【高并发】线程池介绍​​》,作者: 冰 河 。

1.new Thread弊端

(1)每次new Thread新建对象,性能差。

(2)线程缺乏统一管理,可能无限制的新建线程,相互竞争,有可能占用过多系统资源导致死机或OOM。

(3)缺少更多的功能,如更多执行、定期执行、线程中断。

2.线程池的好处

(1)重用存在的线程,减少对象创建、消亡的开销,性能佳。

(2)可以有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞。

(3)提供定时执行、定期执行、单线程、并发数控制等功能。

线程池 - ThreadPoolExecutor

ThreadPoolExecutor参数最多的构造方法如下:

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

接收如下参数进行初始化:

(1)corePoolSize:核心线程数量。
(2)maximumPoolSize:最大线程数。
(3)workQueue:阻塞队列,存储等待执行的任务,很重要,会对线程池运行过程产生重大影响。

三个参数的关系如下:

如果运行的线程数小于corePoolSize,直接创建新线程处理任务,即使线程池中的其他线程是空闲的。

如果运行的线程数大于等于corePoolSize,并且小于maximumPoolSize,此时,只有当workQueue满时,才会创建新的线程处理任务。

如果设置的corePoolSize与maximumPoolSize相同,那么创建的线程池大小是固定的,此时,如果有新任务提交,并且workQueue没有满时,就把请求放入到workQueue中,等待空闲的线程,从workQueue中取出任务进行处理。

如果运行的线程数量大于maximumPoolSize,同时,workQueue已经满了,会通过拒绝策略参数rejectHandler来指定处理策略。

线程池处理任务方式

当提交一个新的任务到线程池时,线程池会根据当前线程池中正在运行的线程数量来决定该任务的处理方式。处理方式总共有三种:直接切换、使用无限队列、使用有界队列。

直接切换常用的队列就是SynchronousQueue。

使用无限队列就是使用基于链表的队列,比如:LinkedBlockingQueue,如果使用这种方式,线程池中创建的最大线程数就是corePoolSize,此时maximumPoolSize不会起作用。当线程池中所有的核心线程都是运行状态时,提交新任务,就会放入等待队列中。

使用有界队列使用的是ArrayBlockingQueue,使用这种方式可以将线程池的最大线程数量限制为maximumPoolSize,可以降低资源的消耗。但是,这种方式使得线程池对线程的调度更困难,因为线程池和队列的容量都是有限的了。

降低系统资源消耗措施

如果想降低系统资源的消耗,包括CPU使用率,操作系统资源的消耗,上下文环境切换的开销等,可以设置一个较大的队列容量和较小的线程池容量。这样,会降低线程处理任务的吞吐量。

如果提交的任务经常发生阻塞,可以考虑调用设置最大线程数的方法,重新设置线程池最大线程数。如果队列的容量设置的较小,通常需要将线程池的容量设置的大一些,这样,CPU的使用率会高些。如果线程池的容量设置的过大,并发量就会增加,则需要考虑线程调度的问题,反而可能会降低处理任务的吞吐量。

(4)keepAliveTime:线程没有任务执行时最多保持多久时间终止
当线程池中的线程数量大于corePoolSize时,如果此时没有新的任务提交,核心线程外的线程不会立即销毁,需要等待,直到等待的时间超过了keepAliveTime就会终止。
(5)unit:keepAliveTime的时间单位
(6)threadFactory:线程工厂,用来创建线程
默认会提供一个默认的工厂来创建线程,当使用默认的工厂来创建线程时,会使新创建的线程具有相同的优先级,并且是非守护的线程,同时也设置了线程的名称
(7)rejectHandler:拒绝处理任务时的策略
如果workQueue阻塞队列满了,并且没有空闲的线程池,此时,继续提交任务,需要采取一种策略来处理这个任务。

线程池总共提供了四种策略:

  • 直接抛出异常,这也是默认的策略。实现类为AbortPolicy。
  • 用调用者所在的线程来执行任务。实现类为CallerRunsPolicy。
  • 丢弃队列中最靠前的任务并执行当前任务。实现类为DiscardOldestPolicy。
  • 直接丢弃当前任务。实现类为DiscardPolicy。

线程池实例的几种状态:

  • Running:运行状态,能接收新提交的任务,并且也能处理阻塞队列中的任务
  • Shutdown: 关闭状态,不能再接收新提交的任务,但是可以处理阻塞队列中已经保存的任务,当线程池处于Running状态时,调用shutdown()方法会使线程池进入该状态
  • Stop: 不能接收新任务,也不能处理阻塞队列中已经保存的任务,会中断正在处理任务的线程,如果线程池处于Running或Shutdown状态,调用shutdownNow()方法,会使线程池进入该状态
  • Tidying: 如果所有的任务都已经终止,有效线程数为0(阻塞队列为空,线程池中的工作线程数量为0),线程池就会进入该状态。
  • Terminated: 处于Tidying状态的线程池调用terminated()方法,会使用线程池进入该状态

注意:不需要对线程池的状态做特殊的处理,线程池的状态是线程池内部根据方法自行定义和处理的。

ThreadPoolExecutor提供的方法

(1)execute():提交任务,交给线程池执行
(2)submit():提交任务,能够返回执行结果 execute+Future
(3)shutdown():关闭线程池,等待任务都执行完
(4)shutdownNow():立即关闭线程池,不等待任务执行完

适用于监控的方法如下:

(1)getTaskCount():线程池已执行和未执行的任务总数
(2)getCompletedTaskCount():已完成的任务数量
(3)getPoolSize():线程池当前的线程数量
(4)getActiveCount():当前线程池中正在执行任务的线程数量

线程池 - Executor框架接口

(1)Executors.newCachedThreadPool:创建一个可缓存的线程池,如果线程池的大小超过了需要,可以灵活回收空闲线程,如果没有可回收线程,则新建线程
(2)Executors.newFixedThreadPool:创建一个定长的线程池,可以控制线程的最大并发数,超出的线程会在队列中等待
(3)Executors.newScheduledThreadPool:创建一个定长的线程池,支持定时、周期性的任务执行
(4)Executors.newSingleThreadExecutor: 创建一个单线程化的线程池,使用一个唯一的工作线程执行任务,保证所有任务按照指定顺序(先入先出或者优先级)执行

线程池 - 合理配置

(1)CPU密集型任务,就需要尽量压榨CPU,参考值可以设置为NCPU+1(CPU的数量加1)。
(2)IO密集型任务,参考值可以设置为2*NCPU(CPU数量乘以2)


点击关注,第一时间了解华为云新鲜技术~

标签:处理,队列,好处,任务,了解,线程,workQueue,执行
From: https://blog.51cto.com/u_15214399/6093326

相关文章

  • 还不知道线程池的好处?快来了解一下
    摘要:线程池的好处:重用存在的线程,减少对象创建、消亡的开销,性能佳;可以有效控制最大并发线程数,提高系统资源利用率,同时可以避免过多资源竞争,避免阻塞。本文分享自华为云社区......
  • jmeter跨线程组调用变量-以token为例
    跨线程组调用变量的解决方法:在beanshell取样器中使用setProperty函数设置全局变量,其他线程组用P函数调用全局变量 跨线程组调用变量的步骤:以token为例跨线程组调用有两......
  • 第8章:多线程
    第8章多线程1、基本概念:程序、进程、线程程序(program):是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。进程(process):是程序的一次执......
  • Java——四种线程创建方式
    java中创建线程有四种方式,分别是:继承Thread类,重写run方法,然后创建线程对象并调用start方法。实现Runnable接口,实现run方法,然后创建线程对象并传入Runnable实例,再调用start......
  • 深入了解视觉语言模型
    人类学习本质上是多模态(multi-modal)的,因为联合利用多种感官有助于我们更好地理解和分析新信息。理所当然地,多模态学习的最新进展即是从这一人类学习过程的有效性中汲取......
  • C# Winform 多线程更新界面UI控件,解决界面卡顿问题(转)
    前言    多线程刷新界面主要用到多线程,委托,线程安全、事件等一系列高难度的C#操作。1、使用timer控件对要刷新的控件进行定时刷新    对刷新频率要求不......
  • idea 多线程debug设置
    断点上右键—选Thread,如图:......
  • (转)一文了解 Go 标准库 strings 常用函数和方法
    原文:https://blog.csdn.net/weixin_44604586/article/details/128104981?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EYu......
  • IO相关了解
    1.IO的概念IO简单来讲就是对输入输出设备的简化表达形式单片机中各种接口,进行数据流的传输从磁盘中读取数据至内存,又或者从内存中写入磁盘编程中的IO此时的IO其......
  • 查看线程状态
    packagecom.study.concurrent.thread.state;importstaticjava.lang.Thread.*;publicclassThreadStateDemo1_Sleep{staticvolatilebooleanrunning=true;p......