目录

一、线程池是什么?

二、Executors创建

1.FixedThreadPool(一池多线程)

2.newCachedThreadPool(可缓存线程池)

3.newSingleThreadExecutor(一池一线程)

4.newScheduledThreadPool(任务线程池)

三、自定义线程池ThreadPoolExecutor

总结



一、线程池是什么?

        线程池是一个用于管理和优化线程使用的设计模式,特别是在执行大量任务或处理并发请求时。它通过维护一定数量的可重用线程来提升应用程序的性能。它有2种类创建方式:

1, 通过 ThreadPoolExecutor 手动创建线程池。
2, 通过 Executors 执行器自动创建线程池

二、Executors创建

Executors创建常见有4种类型:

Executors.newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。

Executors.newCachedThreadPool:创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。

Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执行顺序。

Executors.newScheduledThreadPool:创建一个可以执行延迟任务的线程池。 

1.FixedThreadPool(一池多线程)

创建一个固定线程数的线池,初始容量为5的线程池

代码如下(示例):


public class fixThread {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(5);//设置线程初始容量为5

for (int i = 0; i < 10; i++) {
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName() + "正在执行中");
});
}


}
}


 

2.newCachedThreadPool(可缓存线程池)

创建一个可缓存线程池,它的特点是根据需求创线程数,不需要指定数量

代码如下(示例):

//可缓存线程池
public class CacheThread {
public static void main(String[] args) {

ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i <10 ; i++) {
executorService.execute(()->{
System.out.println(Thread.currentThread().getName()+"正在执行中");
});
}

}
}

3.newSingleThreadExecutor(一池一线程)

创建一个线程的线程池,不需要指定数量

public class fixThread {
    public static void main(String[] args) {

        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i <10 ; i++) {
             executorService.execute(()->{
                 System.out.println(Thread.currentThread().getName()+"正在执行中");
             });
        }

    }
}

4.newScheduledThreadPool(任务线程池)

public class fixThread {
public static void main(String[] args) {

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

for (int i = 0; i <10 ; i++) {
scheduledExecutorService.schedule(()->{
System.out.println(Thread.currentThread().getName()+"正在执行延迟任务");
},5, TimeUnit.SECONDS);
}

}

三、自定义线程池ThreadPoolExecutor

七大参数:

1,int corePoolSize, //核心线程数,线程池一直存在的线程数
2,int maximumPoolSize, //最大线程数,超过核心线程池另外运行存在的线程数
3,long keepAliveTime, //存活时间,最大线程数的不被使用的存活时间
4,TimeUnit unit,//存活单位
5,BlockingQueue<Runnable> workQueue)  //工作队列
6,Executors.defaultThreadFactory()//线程工厂

7,defaultHandler  拒绝策略 任务超过线程可以处理的任务时候,采取的处理方式

public class fixThread {
public static void main(String[] args) {

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5,10,5,TimeUnit.SECONDS,new ArrayBlockingQueue<>(5,true),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i <12 ; i++) {
threadPoolExecutor.execute(()->{
System.out.println(Thread.currentThread().getName()+"执行中");
});
}

}
}

ThreadPoolExecutor 相比于其他创建线程池的优势在于,它可以通过参数来控制最大任务数和拒绝策略,让线程池的执行更加透明和可控,所以在阿里巴巴《Java开发手册》是这样规定的:

【强制要求】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。

说明:Executors 返回的线程池对象的弊端如下:
1) FixedThreadPool 和 SingleThreadPool:允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
2)CachedThreadPool:允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。


总结

线程池的常见创建方式有以下 5 种:

Executors.newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。

Executors.newCachedThreadPool:创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。

Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执行顺序。

Executors.newScheduledThreadPool:创建一个可以执行延迟任务的线程池。

ThreadPoolExecutor:手动创建线程池的方式,它创建时最多可以设置 7 个参数。

而线程池的创建推荐使用最后一种 ThreadPoolExecutor 的方式来创建,因为使用它可以明确线程池的运行规则,规避资源耗尽的风险。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐