为什么推荐使用线程池?

为什么推荐使用线程池?

 更多优秀文章,请扫码关注个人微信公众号或搜索“程序猿小杨”添加。

背景:

  若并发的线程数量很多,且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。那么有没有一种办法使得线程可以复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务?

使用线程池可以解决上述问题:

   1、为多线程执行琐碎的任务提供支持; (并发的线程数非常多,且每个执行时间很短就结束);

   2、避免频繁线程创建、销毁过程的资源消耗;(因为频繁创建线程和销毁线程需要时间)

   3、控制资源的使用,根据实际情况合理高效利用资源。(那么有没有一种办法使得线程可以复用)

使用线程池的好处:

       1、降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

      2、提升响应速度:当任务到达时,不需要等到线程创建就能立即执行。

       3、对线程做统一管理:线程是稀缺资源,若无限制创建,不仅消耗系统资源,还会降低系统稳定性,使用线程池可以统一分配、调优和监控。

核心ThreadPoolExecutor类:

    1、使用JDK线程池ThreadPoolExecutor;

    2、使用Spring包下ThreadPoolTaskExecutor多线程。

ThreadPoolExecutor提供的构造函数:

 7.1、corePoolSize:该线程池中核心线程数最大值。

       线程池中有两类线程,核心线程和非核心线程。核心线程默认情况下会一直存在于线程池中,即使这个核心线程什么都不干(铁饭碗),而非核心线程如果长时间的闲置,就会被销毁(临时工)。

7.2、maximumPoolSize:该线程池中线程总数最大值。

  该值等于核心线程数量(corePoolSize) + 非核心线程数量。

7.3、keepAliveTime:非核心线程闲置超时时长。

   非核心线程如果处于闲置状态超过该值,就会被销毁。如果设置allowCoreThreadTimeOut(true)默认false,则会也作用于核心线程。

      如果线程池设置了allowCoreThreadTimeout参数为true,那么当空闲线程超过keepaliveTime后直接停掉。(不会判断线程数是否大于corePoolSize)即:最终线程数会变为0。一般使用默认false即可。

7.4、TimeUnit:表示keepAliveTime的单位。

timeunit.days;               //天timeunit.hours;             //小时timeunit.minutes;           //分钟timeunit.seconds;           //秒timeunit.milliseconds;      //毫秒timeunit.microseconds;      //微妙timeunit.nanoseconds;       //纳

       当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉,所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。

7.5、BlockingQueue<Runnable> workQueue:阻塞队列。

常用的几个阻塞队列:

  1、LinkedBlockingQueue:链式阻塞队列,底层数据结构是链表,默认大小是Integer.MAX_VALUE,也可以指定大小。(无界队列)

  2、ArrayBlockingQueue:数组阻塞队列,底层数据结构是数组,需要指定队列的大小。(有界队列)

  3、SynchronousQueue:同步队列,内部容量为0,每个put操作必须等待一个take操作,反之亦然。(有界队列)

  4、DelayQueue:延迟队列,该队列中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素 。

  注意:keepAliveTime和maximumPoolSize及BlockingQueue的类型均有关系。如果BlockingQueue是无界的,那么永远不会触发maximumPoolSize,自然keepAliveTime也就没有了意义。ArrayBlockingQueue和DelayQueue使用较少,一般使用LinkedBlockingQueue和SynchronousQueue

7.6、ThreadFactory:创建线程的工厂。

       创建线程的工厂,用于批量创建线程,统一在创建线程时设置一些参数,如是否守护线程、线程的优先级等。如果不指定,会新建一个默认的线程工厂。

  默认工厂创建的线程:同属于相同的线程组,具有同为 Thread.NORM_PRIORITY 的优先级,以及名为 “pool-XXX-thread-” 的线程名(XXX为创建线程时顺序序号),且创建的线程都是非守护进程。

  例如:pool-5-thread-6。

7.7、RejectedExecutionHandler:拒绝处理策略。

      线程数量大于最大线程数(maximumPoolSize)就会采用拒绝处理策略,四种拒绝处理的策略为:

    1、ThreadPoolExecutor.AbortPolicy默认拒绝处理策略,丢弃任务并抛出RejectedExecutionException异常。(默认)

    2、ThreadPoolExecutor.DiscardPolicy:丢弃新来的任务,但是不抛出异常。

   3、ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列头部(最旧的)的任务,然后重新尝试执行程序(如果再次失败,重复此过程)。

    4、ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务。

    备注:最科学的的还是 AbortPolicy 提供的处理方式:抛出异常,由开发人员进行处理。

更多优秀文章,请扫码关注个人微信公众号或搜索“程序猿小杨”添加。

推荐文章:

    1、SpringBoot使用@Async实现多线程异步;

    2、线程池的主要处理流程及常用方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值