JAVA中创建线程池主要有两类方法,一类是通过Executors工厂类提供的方法,该类提供了4种不同的线程池可供使用。另一类是通过ThreadPoolExecutor类进行自定义创建。
目录
一、通过Executors类提供的方法。
1、newCachedThreadPool
2、newFixedThreadPool
3、newScheduledThreadPool
4、newSingleThreadExecutor
二、通过ThreadPoolExecutor类自定义。
三、总结。
一、通过Executors类提供的方法。
1、newCachedThreadPool
创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。
代码例子:
private static void createCachedThreadPool() {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 10; i++) {
final int index = i;
executorService.execute(() -> {
// 获取线程名称,默认格式:pool-1-thread-1
System.out.println(Thread.currentThread().getName() + " " + index);
// 等待2秒
sleep(2000);
});
}
}
效果:
2、newFixedThreadPool
创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。
代码例子:
private static void createFixedThreadPool() {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; i++) {
final int index = i;
executorService.execute(() -> {
// 获取线程名称,默认格式:pool-1-thread-1
System.out.println(Thread.currentThread().getName() + " " + index);
// 等待2秒
sleep(2000);
});
}
}
效果:
3、newScheduledThreadPool
创建一个周期性的线程池,支持定时及周期性执行任务。
代码例子:
private static void createScheduledThreadPool() {
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);
System.out.println("提交任务");
for (int i = 0; i < 10; i++) {
final int index = i;
executorService.schedule(() -> {
// 获取线程名称,默认格式:pool-1-thread-1
System.out.println(Thread.currentThread().getName() + " " + index);
// 等待2秒
sleep(2000);
}, 3, TimeUnit.SECONDS);
}
}
效果:
注意:这里用的是ScheduledExecutorService类的schedule()方法,不是ExecutorService类的execute()方法。
4、newSingleThreadExecutor
创建一个单线程的线程池,可保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
代码例子:
private static void createSingleThreadPool() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
for (int i = 0; i < 10; i++) {
final int index = i;
executorService.execute(() -> {
// 获取线程名称,默认格式:pool-1-thread-1
System.out.println(Thread.currentThread().getName() + " " + index);
// 等待2秒
sleep(2000);
});
}
}
效果:
二、通过ThreadPoolExecutor类自定义。
ThreadPoolExecutor类提供了4种构造方法,可根据需要来自定义一个线程池。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
// 省略...
}
1、共7个参数如下:
(1)corePoolSize:核心线程数,线程池中始终存活的线程数。
(2)maximumPoolSize: 最大线程数,线程池中允许的最大线程数。
(3)keepAliveTime: 存活时间,线程没有任务执行时最多保持多久时间会终止。
(4)unit: 单位,参数keepAliveTime的时间单位,7种可选。
(5)workQueue: 一个阻塞队列,用来存储等待执行的任务,均为线程安全,7种可选。
(6)threadFactory: 线程工厂,主要用来创建线程,默及正常优先级、非守护线程。
(7)handler:拒绝策略,拒绝处理任务时的策略,4种可选,默认为AbortPolicy。
2、顺便说下线程池的执行规则如下:
(1)当线程数小于核心线程数时,创建线程。
(2)当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
(3)当线程数大于等于核心线程数,且任务队列已满:
若线程数小于最大线程数,创建线程。
若线程数等于最大线程数,抛出异常,拒绝任务。
代码例子:
private static void createThreadPool() {
ExecutorService executorService = new ThreadPoolExecutor(2, 10,
1, TimeUnit.MINUTES, new ArrayBlockingQueue<>(5, true),
Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i < 10; i++) {
final int index = i;
executorService.execute(() -> {
// 获取线程名称,默认格式:pool-1-thread-1
System.out.println(Thread.currentThread().getName() + " " + index);
// 等待2秒
sleep(2000);
});
}
}
效果:文章来源:https://www.toymoban.com/news/detail-720793.html
文章来源地址https://www.toymoban.com/news/detail-720793.html
三、总结。
线程池不推荐使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 Executors返回的线程池对象的弊端如下: FixedThreadPool和SingleThreadPool:允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。 CachedThreadPool和ScheduledThreadPool:允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
到了这里,关于NO.17 JAVA中创建线程池的五种方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!