1. newFixedThreadPool 固定数目线程的线程池
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());}
线程池特点:
外围线程数和最大线程数大小一样
没有所谓的非闲暇工夫,即keepAliveTime为0
阻塞队列为无界队列LinkedBlockingQueue
工作机制:
- 提交工作
- 如果线程数少于外围线程,创立外围线程执行工作
- 如果线程数等于外围线程,把工作增加到LinkedBlockingQueue阻塞队列
- 如果线程执行完工作,去阻塞队列取工作,继续执行。
应用无界队列的线程池会导致内存飙升吗?
会的,newFixedThreadPool应用了无界的阻塞队列LinkedBlockingQueue,如果线程获取一个工作后,工作的执行工夫比拟长,会导致队列的工作越积越多,导致机器内存应用不停飙升,最终导致OOM。
应用场景
FixedThreadPool 实用于解决CPU密集型的工作,确保CPU在长期被工作线程应用的状况下,尽可能的少的调配线程,即实用执行长期的工作。
newCachedThreadPool 可缓存线程的线程池
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory);}
线程池特点:
外围线程数为0
最大线程数为Integer.MAX_VALUE
阻塞队列是SynchronousQueue
非核心线程闲暇存活工夫为60秒
当提交工作的速度大于解决工作的速度时,每次提交一个工作,就必然会创立一个线程。极其状况下会创立过多的线程,耗尽CPU和内存资源。因为闲暇 60 秒的线程会被终止,长时间放弃闲暇的 CachedThreadPool 不会占用任何资源。
工作机制
- 提交工作
- 因为没有外围线程,所以工作间接加到SynchronousQueue队列。
- 判断是否有闲暇线程,如果有,就去取出工作执行。
- 如果没有闲暇线程,就新建一个线程执行。
- 执行完工作的线程,还能够存活60秒,如果在这期间,接到工作,能够持续活下去;否则,被销毁。
应用场景
用于并发执行大量短期的小工作。
newSingleThreadExecutor 单线程的线程池
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()));}
线程池特点
外围线程数为1
最大线程数也为1
阻塞队列是LinkedBlockingQueue
keepAliveTime为0
工作机制
- 提交工作
- 线程池是否有一条线程在,如果没有,新建线程执行工作
- 如果有,将工作加到阻塞队列
- 以后的惟一线程,从队列取工作,执行完一个,再持续取,一个人(一条线程)披星戴月地干活。
应用场景
实用于串行执行工作的场景,一个工作一个工作地执行。
newScheduledThreadPool 定时及周期执行的线程池
public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());}
线程池特点
最大线程数为Integer.MAX_VALUE
阻塞队列是DelayedWorkQueue
keepAliveTime为0
scheduleAtFixedRate() :按某种速率周期执行
scheduleWithFixedDelay():在某个提早后执行
工作机制
- 增加一个工作
- 线程池中的线程从 DelayQueue 中取工作
- 线程从 DelayQueue 中获取 time 大于等于以后工夫的task
- 执行完后批改这个 task 的 time 为下次被执行的工夫
- 这个 task 放回DelayQueue队列中
应用场景
周期性执行工作的场景,须要限度线程数量的场景