并行:多核cpu同时处理多件事
并发:伪并行
继承关系:ThreadPoolExecutor->ExecutorService->Executor
Executors:ThreadPoolExecutor的工厂类,生成不同的线程池
线程池:接口:ExecutorService->实现类ThreadPoolExecutor
1:int corePoolSize (core:核心的) = > 该线程池中核心线程数最大值
什么是核心线程:线程池新建线程的时候,如果当前线程总数小于 corePoolSize ,则新建的是核心线程;如果超过corePoolSize,则新建的是非核心线程。
默认情况下核心线程会一直存活在线程池中,即使这个核心线程啥也不干(闲置状态)。
如果指定ThreadPoolExecutor
的allowCoreThreadTimeOut
这个属性为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);
}
网友评论