多线程 之 线程池的深入理解

本文参考资料:https://www.jianshu.com/p/87bff5cc8d8c

线程池的执行流程

       首先,我们假设创建一个线程池:

ThreadPoolExecutor pool = new ThreadPoolExecutor(4, 8, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(20));

        当线程池首次被使用的时候,来一个任务,就会创建一个线程去执行,一直创建4个核心线程,当第5个任务加入的时候,就会将第5-24个任务放入队列中,当第25-28个任务加入的时候,还是没有线程空闲出来,就会创建一个线程去执行,这时候存活线程已经和最大线程相等,在加入任务时,就会执行拒绝策略,默认是直接报异常,抛弃任务.一般我们需要实现RejectedExecutionHandler接口,可以记录抛弃的日志,也可以持久化任务等.

       

创建线程池

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);

    }

 
    corePoolSize:核心池大小,如果执行了线程池的prestartAllCoreThreads()方法,线程池会提前创建并启动所有核心线程;如果                              没有,线程池启动的时候,每创建一个任务,才会创建一个线程,直到线程数量等于corePoolSize;
    maximumPoolSize:线程池中允许的最大线程数。如果当前阻塞队列满了,且继续提交任务,则创建新的线程执行任务,前                                 提是当前线程数小于maximumPoolSize
    keepAlivertime:当活跃线程数大于核心线程数,空闲的多余线程最大存活时间。
    unit:keepAlivertime存活时间的单位
    workQueue:用来保存等待被执行的任务的阻塞队列,且任务必须实现Runable接口,在JDK中提供了如下阻塞队列:
                          1、ArrayBlockingQueue:基于数组结构的有界阻塞队列,按FIFO排序任务;
                          2、LinkedBlockingQuene:基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于                                                               ArrayBlockingQuene;
                           3、SynchronousQuene:一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则                                 插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQuene;
                           4、priorityBlockingQuene:具有优先级的无界阻塞队列;
    handler: 线程池的饱和策略,当阻塞队列满了,且没有空闲的工作线程,如果继续提交任务,必须采取一种策略处理该任务,         

           线程池提供了4种策略:

                 1、AbortPolicy:直接抛出异常,默认策略;
                 2、CallerRunsPolicy:用调用者所在的线程来执行任务;
                 3、DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务;
                 4、DiscardPolicy:直接丢弃任务;
                   当然也可以根据应用场景实现RejectedExecutionHandler接口,自定义饱和策略,如记录日志或持久化存储不能处理                    的任务。

  Exectors

Exectors工厂类提供了线程池的初始化接口,主要有如下几种:

newFixedThreadPool

初始化一个指定线程数的线程池,其中corePoolSize == maximumPoolSize,使用LinkedBlockingQuene作为阻塞队列,不过当线程池没有可执行任务时,也不会释放线程。

newCachedThreadPool

1、初始化一个可以缓存线程的线程池,默认缓存60s,线程池的线程数可达到Integer.MAX_VALUE,即2147483647,内部使用SynchronousQueue作为阻塞队列;
2、和newFixedThreadPool创建的线程池不同,newCachedThreadPool在没有任务执行时,当线程的空闲时间超过keepAliveTime,会自动释放线程资源,当提交新任务时,如果没有空闲线程,则创建新线程执行任务,会导致一定的系统开销;

所以,使用该线程池时,一定要注意控制并发的任务数,否则创建大量的线程可能导致严重的性能问题。

newSingleThreadExecutor

初始化的线程池中只有一个线程,如果该线程异常结束,会重新创建一个新的线程继续执行任务,唯一的线程可以保证所提交任务的顺序执行,内部使用LinkedBlockingQueue作为阻塞队列。

newScheduledThreadPool

初始化的线程池可以在指定的时间内周期性的执行所提交的任务,在实际的业务场景中可以使用该线程池定期的同步数据。


本文参考资料:https://www.jianshu.com/p/87bff5cc8d8c

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值