我的原则:先会用再说,内部慢慢来。
学以致用,根据场景学源码
一、工具类 Executors
1.1 UML 图
1.2 四个常用方法
方法 | 描述 |
---|---|
newCachedThreadPool | 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 (线程可复用) |
newFixedThreadPool | 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 |
newScheduledThreadPool | 创建一个定长线程池,支持定时及周期性任务执行。 |
newSingleThreadExecutor | 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 |
1.3 线程池的作用
- 提供了一个线程队列,队列中保存着所有等待状态的线程。避免了创建与销毁额外开销,提高了相应速度。
二、实战
2.1 newCachedThreadPool 方法
- java.util.concurrent.Executors#newCachedThreadPool() 方法,内部线程数量默认 Integer.MAX_VALUE ,线程池为无限大。
- newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
- 当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
public static void method_newCachedThreadPool() {
// 1、创建线程池
ExecutorService pool = Executors.newCachedThreadPool();
// 2、分配任务
for (int i = 0; i < 20; i++) {
final int index = i;
pool.execute(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-" + index);
}
);
}
// 3、关闭线程池
pool.shutdown();
}
输出:
pool-1-thread-2-1
pool-1-thread-9-8
pool-1-thread-10-9
pool-1-thread-1-0
pool-1-thread-12-11
pool-1-thread-14-13
pool-1-thread-15-14
pool-1-thread-17-16
pool-1-thread-18-17
pool-1-thread-19-18
pool-1-thread-20-19
pool-1-thread-8-7
pool-1-thread-13-12
pool-1-thread-6-5
pool-1-thread-7-6
pool-1-thread-3-2
pool-1-thread-5-4
pool-1-thread-16-15
pool-1-thread-4-3
pool-1-thread-11-10
2.2 newFixedThreadPool 方法
- java.util.concurrent.Executors#newFixedThreadPool(int)
- newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
public static void method_newFixedThreadPool() {
// 1、创建线程池
ExecutorService pool = Executors.newFixedThreadPool(4);
// 2、分配任务
for (int i = 0; i < 10; i++) {
final int index = i;
pool.execute(() -> {
System.out.println(Thread.currentThread().getName() + "-" + index);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
// 3、关闭线程池
pool.shutdown();
}
- 因为线程池大小为4,每个任务输出index后sleep 2秒,所以每两秒打印4个数字。
- 输出:
pool-1-thread-1-0
pool-1-thread-2-1
pool-1-thread-3-2
pool-1-thread-4-3
pool-1-thread-3-4
pool-1-thread-1-7
pool-1-thread-2-6
pool-1-thread-4-5
2.3 newScheduledThreadPool 方法
-
java.util.concurrent.Executors#newScheduledThreadPool(int) 规定池内线程最大数量
-
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
public static void newScheduledThreadPoolSchedule() {
// 1、创建线程池
ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
// 2、分配任务
// 启动了两个定时的任务,在JVM开启后的1分钟后,每隔2分钟,开始执行一次。
LoopCount loopCount = new LoopCount();
for (int i = 0; i < 2; i++) {
final int index = i;
pool.scheduleAtFixedRate(() -> System.out.println(Thread.currentThread().getName() + "-" + index + "_count_" + loopCount.getCount().incrementAndGet()),
1, 2, TimeUnit.SECONDS);
}
}
@Data
static class LoopCount{
private AtomicInteger count = new AtomicInteger(0);
}
- 定时及周期性任务操作 scheduleAtFixedRate
- java.util.concurrent.ScheduledExecutorService#scheduleAtFixedRate 方法
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit)
- 启动了两个定时的任务,在JVM开启后的1分钟后,每隔2分钟,开始执行一次。
- 输出:
pool-1-thread-1-0_count_1
pool-1-thread-2-1_count_2
pool-1-thread-2-0_count_3
pool-1-thread-1-1_count_4
pool-1-thread-3-0_count_5
pool-1-thread-2-1_count_6
pool-1-thread-3-0_count_7
pool-1-thread-1-1_count_8
pool-1-thread-2-0_count_9
pool-1-thread-3-1_count_10
pool-1-thread-1-0_count_11
pool-1-thread-1-1_count_12
pool-1-thread-1-0_count_13
2.4 newSingleThreadExecutor 方法
- java.util.concurrent.Executors#newSingleThreadExecutor()
- 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
public static void method_newSingleThreadExecutor() {
// 1、创建线程池
ExecutorService pool = Executors.newSingleThreadExecutor();
// 2、分配任务
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
final int index = i;
pool.execute(() -> System.out.println(Thread.currentThread().getName() + "-" + index));
}
// 3、关闭线程池
pool.shutdown();
}
输出:
pool-1-thread-1-0
pool-1-thread-1-1
pool-1-thread-1-2
pool-1-thread-1-3
pool-1-thread-1-4
pool-1-thread-1-5
pool-1-thread-1-6
pool-1-thread-1-7
pool-1-thread-1-8
pool-1-thread-1-9
- 结论:逐个输出,先进先执行 FIFO。
=== 点击查看top目录 ===
三、番外篇
下一章节:【线程】ThreadPool 线程池底层剖析 (二十)
上一章节:【线程】Thread.UncaughtExceptionHandler 实战与剖析 (十八)