共计 1945 个字符,预计需要花费 5 分钟才能阅读完成。
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 队列中
应用场景
周期性执行工作的场景,须要限度线程数量的场景