首页 > 其他分享 >线程池总结

线程池总结

时间:2023-02-16 19:36:19浏览次数:33  
标签:总结 队列 创建 可以 任务 线程 使用

一、什么是线程池,为什么需要线程池

池化思想在计算机领域并不少见,在SQL连接,TCP链接中也常常见到,本质思想都是一样的,就是资源复用,线程池也差不多就是这个道理,它将多个线程资源先存储在一个池子中,,当有新的任务出现时可以避免创建/销毁线程所带来的性能开销,只要复用池子中的线程来执行对应的任务即可。
总而言之,就是使用线程池这个工具可以更好地管理线程,避免不必要的开销和内存的占用。

二、线程池的工作原理

线程池只要两个数据结构来配合工作,一个是阻塞队列BlockQueue,另一个就是线程池,它们的关系如图

线程池还包括核心线程池,这个图没有画出(我懒得画了,也没有找到合适的图片)
Question1:线程池添加线程的规则(经典八股文,不过还算是有意义的八股文)

  1. 当前线程数小于核心线程数,则不管工作线程有没有空闲的,都会创建一个新的线程来解决对应的任务
  2. 如果当前线程数大于核心线程数,但小于最大线程数,那么新来的任务加入工作队列中
  3. 如果工作队列满了,但当前线程数还是小于最大线程数,则创建新的线程放入线程池中运行任务
  4. 如果队列满了,并且当前线程数已经超过最大线程数了,那么就拒绝这个任务。

Question2:线程池的关键参数
从上面的提交流程也可以看出几个关键参数,核心线程数corePoolSize,mazPoolSize, workQueue, Handler(拒绝策略),此外我们还可以设置线程存活时间keepAlive,和创建线程的工厂模式(可以指定线程的线程名,线程优先级,线程是否为守护线程)(不过不常用)

Question3:如何创建线程池
阿里巴巴的《java开发手册》中这样写

【强制要求】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

至于如何合理配置相关参数,本人还没参加工作,还不会,以后秃头了再来补充(不知道要几年了)
Question4:为什么不要用Executors创建线程池
虽说这样创建不好,但是在平时学习的时候,使用Executors还是比较方便的,因为它提供了几个接口来创建线程池

  • newFixedThreadPool
  • newSingleThreadExecutor
  • newCacheThreadPool

常用的就是这四个,当然还有其他的,我没有用过,可以参考其他大佬
虽然他们很方便使用,但是可以看看它们的源码就知道他们的弊端了,他们底层依旧是调用ThreadPoolExecutor,只不过默认设置的参数不一样

nexFixedThreadPool最大的问题是它核心线程数和最大线程数一样,那么keepAlive参数就无效了,因为这个参数只对核心线程数以外的线程起作用,因此是0,同时它采用的是LinkedBlockingQueue阻塞队列,这个队列跟链表性质一样,没有长度限制,所以容易OOM


同理newFixedThreadPool,它使用的工作队列也是LinkedBlockingQueue,所以也容易导致OOM

newCachedThreadPool最大的问题就是它的最大线程数是没有限制的,这样也容易导致创建过多线程而OOM,同时,它使用的工作队列是SynchronousQueue,这个是容量为0(注意有的地方写的是1其实是不对的)的队列,它不持有任何元素,而是直接传递元素

可以看到即使做了这一层包装,但是各有各的问题,因为实际工作中还是不要使用的好。

Question5:线程池中任务如何提交
常见的有两种方法,一种就是执行execute,这个方法适合没有返回值的任务,而submit会返回一个Future对象,通过Future的get方法获取执行结果,另外对于有调度的线程池,也可以使用schedule的方法,问题不大
Question6:如何停止线程池
使用shutdown方法,这个方法不会立刻停止线程池,而是要等待时间把线程池中的任务运行完,这个等待过程中线程池不会再接受新的任务,使用isShutDown就可以判断线程池有没有关闭,使用isTerminated就可以查看里面线程有没有运行完,如果想要立刻结束线程池那么就可以使用shownDownNow,它有个返回值返回未执行完的任务列表
Question6:线程池的拒绝策略有哪些(饱和策略)
有四种,默认的是直接抛出异常,第二种就是舍弃任务但并没有抛出异常,第三种就是抛弃最老的任务,第四种就是执行谁提交的谁运行策略(一般是主线程提交任务,所以交给主线程去运行)

标签:总结,队列,创建,可以,任务,线程,使用
From: https://www.cnblogs.com/spark-cc/p/17128006.html

相关文章

  • 偏序问题总结
    首先既然讲的是偏序问题,先说明一下偏序关系的概念:偏序关系符号为\(\prec\),是一种满足自反性,反对称性和传递性的关系。好叭我承认上面那个定义不是人可以理解的,这里我对......
  • 【开源需求】C++多线程消息分发架构
    项目【gi_messager】开源项目:https://girakoo.com/联系方式:[email protected]需求简述在多线程环境中,为每个线程提供独立的消息队列MessageLoop。注:主线程默认自动......
  • 谈谈muduo库的销毁连接对象——C++程序内存管理和线程安全的极致体现
    #前言网络编程的连接断开一向比连接建立复杂的多,这一点在陈硕写的muduo库中体现的淋漓尽致,同时也充分体现了C++程序在对象生命周期管理上的复杂性,稍有不慎,满盘皆输。为......
  • 线程基本知识
    多线程基础1.线程相关概念1.1程序(program)最为简单完成特点任务,用某种语言编写的一组指令的集合.最简单的说:就是我们写的代码1.2进程1.进程是指运行中的程序,......
  • 以AQS中acquire()方法为例来分析多线程间的同步与协作
    谈到java中的并发,我们就避不开线程之间的同步和协作问题,谈到线程同步和协作我们就不能不谈谈jdk中提供的AbstractQueuedSynchronizer(翻译过来就是抽象的队列同步器)机......
  • 精确延时---多线程延时阻塞精度asm("nop") nanosleep usleep sleep select
    Linux平台延时之sleep、usleep、nanosleep、select比较 1、sleep的精度是秒2、usleep的精度是微妙,不精确3、select的精度是微妙,精确struct timevaldelay;delay.tv_......
  • C#/.net面试知识点总结(三)【值类型与引用类型】
    C#中什么是值类型与引用类型?值类型:struct、enum、int、float、char、bool、decimal引用类型:class、delegate、interface、array、object、stringC#中堆和栈的区别?栈:......
  • C#/.net面试知识点总结(三)【委托】
    委托是什么?事件是不是一种委托?委托可以把一个方法作为参数带入另一个方法。委托可以理解为指向一个函数的指针。C#的委托是CTS(公共类型系统)规定的5种类型之一。(类类型......
  • 线程基础
    Thread类的每一个实例都表示一个线程,进程是操作系统级别的多任务,JVM就是运行在一个进程中的,所以在Java中我我们只考虑线程#线程状态   1.new:当我们new一个......
  • 进程和线程的区别
    ①进程是资源分配的最小单位,线程是资源调度的最小单位。②线程是在进程下运行的。一个进程可以包含多个线程。③进程有自己的独立地址空间,每启动一个进程,系统就会为它分......