线程池:创建线程池的目的是为了能够重复使用已经创建好的线程,因为线程的创建和销毁都需要消耗资源,这造成了大量资源的浪费。当线程池中的线程被拿去使用后又会被保存在线程池中供下一次其他程序的使用。
线程池参数
corePoolSize:核心线程数,即就是可用的线程数
maximumPoolSize:线程池能容纳的最大线程个数
keepAliveTime:活跃时间,大于核心线程数的线程在规定的时间内没有被使用则会被销毁
Unit:时间单位类型
workQueue:存放没有获取线程的对象
ThreadFactory:线程创建工厂
handler:拒绝策略
工作原理
当提交的任务数了小于核心线程数,则正常执行任务,否则没有获得线程的任务就会进入工作等待队列。进入工作队列前首先要判断工作队列是否已满,若未满,则直接进入,否则创建新的线程。创建新的线程时首先要判断当前线程池中 的线程使用量是否已经大于了线程池的最大容量,若大于则抛出异常或者终止任务,否则正常创建新的线程。
原理图
线程池的方法
newCatchedThreadPool
corePoolsize等于maximumPoolSize,所以每次创建的线程都是核心线程。
线程池最⼤为 Integer.MAX_VALUE。
工作队列是一个synchronizedQueue
在getTask()⽅法,当工作队列中没有任务时,线程不会⼀直阻塞synchronizedQueue.take(),空闲的线程会在60资源秒后自动毁,而不会占用
newFixedThreadPool
corePoolSize等于0,所以每次创建的线程都是非核心线程
工作队列是LinkedBlockingQueue,可以容纳无限多个任务
在getTask()⽅法,当工作队列中没有任务时,线程会⼀直阻塞在LinkedBlockingQueue.take(),空闲的线程不会被销毁,造成了大量的 资源浪费
newSingleThreadPool
只有一个核心线程数并且等于线程池最大容量数,其等待工作队列是LinkedBlockingQueue,存储的容量无限,执行的时候只能有一个线程在执行
newSchueduledThreadPool:
创建一个一定数量的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序的队列结构
线程池的创建
使用Executors创建线程池
ExecutorService service=Executors.newSingleThreadExecutor();
service.submit(new Thread(new Runnable() {
@Override
public void run() {
}
}));
使用这种方式创建的线程池会出现OOM的情况,因为Executors里面的几个方法创建线程的大小是Integer.MAX_VALUE newFixedThreadPool中创建LinkedBlockingQueue时,并未指定容量。此时,LinkedBlockingQueue就是一个无边界队列,对于一个无边界队列来说,是可以不断的向队列中加入任务的,这种情况下就有可能因为任务过多而导致内存溢出问题。newCachedThreadPool和newScheduledThreadPool这两个方法也不安全,+
6创建的最大线程数可能是Integer.MAX_VALUE,而创建这么多线程,必然就有可能导致OOM。
使用 ThreadPoolExecutor创建线程池(常使用)
ThreadFactory threadFactory= new ThreadFactoryBuilder();
ExecutorService executorService=new ThreadPoolExecutor(10,20,5, TimeUnit.SECONDS,
new LinkedBlockingDeque<Runnable>(100),threadFactory ,new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i < 10; i++) {
executorService.execute(new Thread(new Runnable() {
@Override
public void run() {
int j=0;
System.out.println(++j);
}
}) );
System.out.println(i);
}
提交的线程数超过当前可用线程数时,就会抛出java.util.concurrent.RejectedExecutionException,这是因为当前线程池使用的队列是有边界队列,队列已经满了便无法继续处理新的请求。但是异常(Exception)总比发生错误(Error)要好。