线程池

2018-07-10  本文已影响25人  蒸汽飞船

并行:多核cpu同时处理多件事
并发:伪并行

继承关系:ThreadPoolExecutor->ExecutorService->Executor
Executors:ThreadPoolExecutor的工厂类,生成不同的线程池

线程池:接口:ExecutorService->实现类ThreadPoolExecutor
1:int corePoolSize (core:核心的) = > 该线程池中核心线程数最大值
什么是核心线程:线程池新建线程的时候,如果当前线程总数小于 corePoolSize ,则新建的是核心线程;如果超过corePoolSize,则新建的是非核心线程。

默认情况下核心线程会一直存活在线程池中,即使这个核心线程啥也不干(闲置状态)。
如果指定ThreadPoolExecutorallowCoreThreadTimeOut这个属性为true,那么核心线程如果不干活(闲置状态)的话,超过一定时间( keepAliveTime),就会被销毁

2:int maximumPoolSize = > 该线程池中线程总数的最大值
线程总数计算公式 = 核心线程数 + 非核心线程数。

3:long keepAliveTime = > 该线程池中非核心线程闲置超时时长
注意:一个非核心线程,如果不干活(闲置状态)的时长,超过这个参数所设定的时长,就会被销毁掉。但是,如果设置了allowCoreThreadTimeOut = true,则会作用于核心线程。

4:TimeUnit unit = > (时间单位)
5:BlockingQueue<Runnable> workQueue = >( Blocking:阻塞的,queue:队列)

workQueue类型:
一般来说,workQueue有以下四种队列类型:

SynchronousQueue:(同步队列)->搭配不限制线程数量

这个队列接收到任务的时候,会直接提交给线程处理,而不保留它(名字定义为 同步队列)。但有一种情况,假设所有线程都在工作怎么办?

这种情况下,SynchronousQueue就会新建一个线程来处理这个任务。所以为了保证不出现(线程数达到了maximumPoolSize而不能新建线程)的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大,去规避这个使用风险。

LinkedBlockingQueue(链表阻塞队列):长度无限的话->线程数不回超过核心线程

当然也可以限定长度,采用队列实现所以说写个100万的长度也没事
这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize

ArrayBlockingQueue(数组阻塞队列):固定长度->超过总线程数报错

可以限定队列的长度(既然是数组,那么就限定了大小),接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误

DelayQueue(延迟队列):

队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务

处理逻辑:
1:如果线程数量未达到corePoolSize,则新建一个线程(核心线程)执行任务
2:如果线程数量达到了corePools,则将任务移入队列等待
3:如果队列已满,新建线程(非核心线程)执行任务
4:如果队列已满,总线程数又达到了maximumPoolSize,就会由RejectedExecutionHandler抛出异常

四种常用的线程池:
1.newFixedThreadPool 固定线程数,队列无限长,超时时间为0

2.newCachedThreadPool:核心线程0,最大线程无限,超时60秒,单一队列

3.newSingleThreadExecutor:只有一个核心线程,队列无限长,超时0

4.newScheduledThreadPool:循环或者延迟任务

ScheduledExecutorService:延时+循环
参考

public interface ScheduledExecutorService extends ExecutorService {
  //延时调用
    public ScheduledFuture<?> schedule(Runnable command,
                                           long delay, TimeUnit unit);

    public <V> ScheduledFuture<V> schedule(Callable<V> callable,
                                           long delay, TimeUnit unit);

    //循环+延时执行:每隔period时间提交一个任务,不关心任务执行时长
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
              long initialDelay,
              long period,
              TimeUnit unit);
    //循环+延时执行:每个任务执行完,再间隔delay再提交任务
    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                             long initialDelay,
                                             long delay,
                                             TimeUnit unit);
}
上一篇 下一篇

猜你喜欢

热点阅读