这世界上没有优秀的理念,只有脚踏实地的结果 。
Executors.newCacheThreadPool():可缓存线程池,先查看线程池中有没有之前创建的线程,如果有则直接使用。否则就新创建一个新的线程加入线程池中,我们经常用此类线程池来执行一些业务处理时间很短的任务。
情况1:
public static void main(String[] args) {
//创建一个可缓存的线程池
ExecutorService executorService = Executors.newCachedThreadPool();
//循环创建10个线程
for (int i = 0; i < 10; i++) {
try {
//模拟线程调用间隔时间
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.submit(() -> {
try {
//模拟业务处理时间
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("使用 newCachedThreadPool-->创建线程:"+Thread.currentThread().getName());
});
}
}
执行结果:
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
使用 newCachedThreadPool-->创建线程:pool-1-thread-1
情况2:我们将模拟业务执行时间改大一点:10ms->1000ms,再次执行结果如下:
使用 newCachedThreadPool-->创建线程:pool-2-thread-1
使用 newCachedThreadPool-->创建线程:pool-2-thread-2
使用 newCachedThreadPool-->创建线程:pool-2-thread-3
使用 newCachedThreadPool-->创建线程:pool-2-thread-4
使用 newCachedThreadPool-->创建线程:pool-2-thread-5
使用 newCachedThreadPool-->创建线程:pool-2-thread-6
使用 newCachedThreadPool-->创建线程:pool-2-thread-7
使用 newCachedThreadPool-->创建线程:pool-2-thread-8
使用 newCachedThreadPool-->创建线程:pool-2-thread-9
使用 newCachedThreadPool-->创建线程:pool-2-thread-10
从上面代码我们就能看出来缓存型线程池的特性。
Executors.newFixedThreadPool():创建一个固定(指定)长度可重用的线程池,可以控制最大创建数,超过最大长度之后就会放入到队列进行等待。
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
executorService.submit(() -> {
try {
//模拟业务处理时间
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("使用 newFixedThreadPool-->创建线程:"+Thread.currentThread().getName());
});
}
}
执行结果:
使用 newFixedThreadPool-->创建线程:pool-1-thread-1
使用 newFixedThreadPool-->创建线程:pool-1-thread-2
使用 newFixedThreadPool-->创建线程:pool-1-thread-3
使用 newFixedThreadPool-->创建线程:pool-1-thread-4
使用 newFixedThreadPool-->创建线程:pool-1-thread-5
使用 newFixedThreadPool-->创建线程:pool-1-thread-6
使用 newFixedThreadPool-->创建线程:pool-1-thread-7
使用 newFixedThreadPool-->创建线程:pool-1-thread-8
使用 newFixedThreadPool-->创建线程:pool-1-thread-9
使用 newFixedThreadPool-->创建线程:pool-1-thread-10
等待3秒钟。。。。。。。
使用 newFixedThreadPool-->创建线程:pool-1-thread-1
使用 newFixedThreadPool-->创建线程:pool-1-thread-2
使用 newFixedThreadPool-->创建线程:pool-1-thread-3
使用 newFixedThreadPool-->创建线程:pool-1-thread-4
使用 newFixedThreadPool-->创建线程:pool-1-thread-5
使用 newFixedThreadPool-->创建线程:pool-1-thread-6
使用 newFixedThreadPool-->创建线程:pool-1-thread-7
使用 newFixedThreadPool-->创建线程:pool-1-thread-8
使用 newFixedThreadPool-->创建线程:pool-1-thread-9
使用 newFixedThreadPool-->创建线程:pool-1-thread-10
等待3秒钟。。。。。。。
使用 newFixedThreadPool-->创建线程:pool-1-thread-1
使用 newFixedThreadPool-->创建线程:pool-1-thread-2
一直到循环100次。。。。
我们创建了一个固定长度为10的线程池,循环100次创建线程,但是我们发现创建的线程数一直没有超过10,这就是定长线程池,此时后面的90个操作都将放到队列等待,等待前面的10个线程执行完毕后,队列里面的才可以继续去创建。
三、创建可定时执行的线程池(ScheduledThreadPool)
Executors.newScheduledThreadPool():创建一个支持定时或周期性的执行任务线程池,可以延时执行,可以用做执行定时任务的线程池。
public static void main(String[] args) {
SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(10);
// 参数的含义依次为:执行线程、初始化延时、线程调用时间间隔、计时单位
executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("线程--->" + Thread.currentThread().getName() + " --->在" + dateFormat.format(new Date()) + "--->执行了此方法。。。");
}
}, 5, 10, TimeUnit.SECONDS);
}
执行结果:
线程--->pool-1-thread-1 --->在2021-04-26 05:21:30--->执行了此方法。。。
线程--->pool-1-thread-1 --->在2021-04-26 05:21:40--->执行了此方法。。。
线程--->pool-1-thread-2 --->在2021-04-26 05:21:50--->执行了此方法。。。
线程--->pool-1-thread-1 --->在2021-04-26 05:22:00--->执行了此方法。。。
线程--->pool-1-thread-3 --->在2021-04-26 05:22:10--->执行了此方法。。。
线程--->pool-1-thread-2 --->在2021-04-26 05:22:20--->执行了此方法。。。
线程--->pool-1-thread-4 --->在2021-04-26 05:22:30--->执行了此方法。。。
线程--->pool-1-thread-1 --->在2021-04-26 05:22:40--->执行了此方法。。。
线程--->pool-1-thread-5 --->在2021-04-26 05:22:50--->执行了此方法。。。
启动程序后,第一次执行方法需要等待5s,后续每10s执行一次。
Executors.newSingleThreadExecutor():创建一个单线程化线程池,它只能用一个工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int number = i;
executorService.submit(() -> {
System.out.println("当前执行编号:" + number);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
执行结果:
当前执行编号:0
当前执行编号:1
当前执行编号:2
当前执行编号:3
当前执行编号:4
当前执行编号:5
当前执行编号:6
当前执行编号:7
当前执行编号:8
当前执行编号:9
执行代码会看到同一时间只有一个线程执行,其余的任务都会有序等待且有序的执行。