Java中提供的线程池的API
1、Executors中提供了几个线程池的工厂方法:
newFixedThreadPool:该方法返回一个固定数量的线程池,线程数不变,当有一个任务提交时,若线程池中空闲,则立即执行,没有,就被暂时缓存到一个任务队列中,等待有空闲到线程去执行。
newSingleThreadPool:创建一个线程的线程池,若空闲则执行,若没有空闲线程则暂缓在任务队列中。
newCachedThreadPool:返回一个可根据实际情况调整线程个数的线程池,不限制最大线程的数量,若有空闲的线程则去执行任务,若没有任务则不创建线程。并且每个空闲的线程会在60秒后自动回收。
newScheduledThread:创建一个可以指定线程的数量的线程池,但是这个线程池还带有延迟和周期性执行任务的功能,类似定时器。
2、创建线程池
private static ExecutorService executorService = Executors.newFixedThreadPool(10);
如上代码所示,初始化线程池 ThreadPoolExecutor,需要初始化的几个属性如下:
corePoolSize:核心线程数量
maximumPoolSize:最大线程数量
keepAliveTime:超时时间,超出核心线程数量以外的线程剩余的存活时间
TimeUnit: 超时时间的单位(ms/s)
workQueue:保存执行任务的队列
threadFactory:创建新线程使用的工厂
handler:当任务无法执行的时候的处理方式
3、阻塞队列
参数workQueue队列指的是用以存储已提交但是未执行的任务,可以作为workQueue队列BlockingQueue接口的实现类有如下几种实现:
1)直接提交队列--SynchronousQueue:
任务数大于maximumPoolSize----->拒绝策略
该队列不会真的保存任务,而是直接交给worker线程执行,如果没有可用的线程就直接创建线程执行,如果worker线程已经超过了maximumPoolSize,就执行拒绝策略;
2)有界的任务队列--ArrayBlockingQueue:
任务加到corePoolSize---->ArrayBlockingQueue---->maximumPoolSize---->拒绝策略
指定队列的大小,有新任务进来,如果当前worker线程数量小于corePoolSize,优先创建线程执行;如果大于corePoolSize,先保存到ArrayBlockingQueue队列中;当超过了ArrayBlockingQueue设定的大小,判断worker线程数如果小于maximumPoolSize,就创建线程执行;如果大于maximumPoolSize,就执行拒绝策略;
3)无界的任务队列--LinkedBlockingQueue:
任务corePoolSize---->LinkedBlockingQueue----->直到耗尽了系统资源
除非系统资源耗尽,否则不存在入队失败的情况;当有新任务进来,如果worker线程数小于corePoolSize就直接创建线程执行;如果大于corePoolSize就很直接加入到LinkedBlockingQueue中;
4)优先任务队列--PriorityBlockingQueue:
该队列可以按照优先级,设置任务被执行的顺序;其他的同ArrayBlckingQueue执行一致;
4、向任务执行
executorService.execute(new ExecutorsServiceDemo())
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
reject(command);
}
ctl的作用
是一个原子类,主要的作用就是保存线程的数量和线程池的状态,因为是int类型的,它的数值就是32位,高3位保存运行的状态,低29位来保存线程的数量。
worker工作线程的5种状态:
RUNNING【-1<< 29】:接收新任务,并执行队列中的任务
SHUTDOWN【0 << 29】:不接收新任务,但是执行队列中的任务
STOP【1<<29】:不接收新任务,不执行队列中的任务,中断正在执行的任务。
TIDYING【2<< 29】:所有的任务都已经结束,线程的数量为0,处于该状态的线程池即将调用terminated()方法。
TERNINATED【3<<29】:terminated()方法执行完成