文章目录
- 🛸前言
- 🌹Executors的三大方法
- 🍔简述线程池
- 🎆手动创建线程池
- ⭐源码分析
- ✨代码实现,手动创建线程池
- 🎈CallerRunsPolicy()
- 🎈AbortPolicy()
- 🎈DiscardPolicy()
- 🎈DiscardOldestPolicy()
🛸前言
🌹Executors的三大方法
Java 中的 Executors 类提供了创建和管理线程池的工厂方法。主要有以下三种常用的静态工厂方法:
-
newFixedThreadPool(int nThreads):固定的线程池大小
创建一个固定大小的线程池,其中包含指定数量的线程。如果所有线程都处于活动状态,并且任务队列已满,那么新任务将在任务队列中等待,直到有空闲的线程可用。
-
newCachedThreadPool():遇强则强,遇弱则弱
创建一个可缓存的线程池,如果线程池的当前规模超过处理需求时,它会回收空闲线程;当需求增加时,则可以添加新的线程,线程池规模不存在限制。
- newSingleThreadExecutor(): 单个线程
创建一个单线程的线程池,该线程池只有一个工作线程,它保证所有任务按顺序执行。
这些工厂方法都返回实现了 ExecutorService 接口的 ThreadPoolExecutor 对象,这是 Java 线程池的一个具体实现,提供了对线程池的操作和控制。通过使用这些工厂方法创建线程池,可以方便快捷地满足不同场景下的线程管理需求。
由于使用Executors不安全,那么我们需要手动创建一个线程池
🍔简述线程池
线程池是一种用于管理和重用线程的机制,它通过预先创建一组线程,并将任务提交给这些线程来执行。线程池可以有效地控制并发线程的数量,避免了频繁创建和销毁线程的开销,提高了系统的性能和资源利用率。
线程池通常由以下组件构成:
- 线程池管理器(ThreadPoolExecutor):负责创建、管理和调度线程池中的线程。它维护着一个线程池的状态,包括线程数量、任务队列、线程工厂等属性。
- 工作线程(Worker Thread):线程池中的实际执行任务的线程。线程池会创建一定数量的工作线程,每个工作线程可以执行多个任务。
- 任务队列(Task Queue):用于存储待执行的任务。当线程池中的线程空闲时,它们会从任务队列中获取任务并执行。
- 线程工厂(Thread Factory):用于创建新的线程对象。线程池在需要创建新线程时,会使用线程工厂创建线程对象。
线程池的主要优点包括:
- 提高系统性能:线程池可以控制并发线程的数量,避免了过多的线程竞争和频繁的线程创建销毁开销,提高了系统的性能。
- 提高资源利用率:线程池可以重用线程,避免了线程创建和销毁的开销,提高了系统的资源利用率。
- 提供线程管理和监控:线程池提供了对线程的管理和监控机制,可以方便地查看线程池的状态、线程执行情况等信息,便于调优和排查问题。
使用线程池时,需要根据具体的业务需求和系统资源情况合理配置线程池的大小、任务队列的容量以及其他相关参数,避免因线程池过小或过大导致的性能问题。
🎆手动创建线程池
⭐源码分析
newSingleThreadExecutor的源码
newFixedThreadPool的源码
newCachedThreadPool的源码
其中有个参数长度是Integer,MAX_VALUE,长度过大,可能会堆积大量的请求,对应了上面我们说的不能用Executors,而要用ThreadPoolExecutors
我们发现,上面三者的源码中都有ThreadPoolExecutor
说明调用线程的本质调用的是ThreadPoolExecutor
下面我们来分析一下ThreadPoolExecutor
下面我们来想象一个场景,来更好的理解线程池
比如我们去银行办理业务
银行有5个窗口,但是只打开了2个(代表核心线程池的大小为2),还有3个没有开(触发最大并发量的情况下才会打开这3个窗口),还有容量为3的候客区(阻塞队列)
然后有用户去办理业务了,假如来了3个用户,2个去窗口了,还有1个在候客区等待,此时,又来了3个用户,这时候客区的位置不够了(阻塞队列满了),就要打开那关闭的3个窗口(触发最大并发量了)
✨代码实现,手动创建线程池
🎈CallerRunsPolicy()
package org.Test6;
import java.util.concurrent.*;
public class Demo01 {
public static void main(String[] args) {
//自定义线程池
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS, //超时等待时间
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
try {
for (int i = 1; i <= 10; i++) {
//使用线程池后,使用线程池来创建线程
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭线程池
threadPool.shutdown();
}
}
}
代码里面的超时等待时间是什么意思
我们对应上面去银行的场景,触发最大并发条件后,所有窗口都打开了,一段时间后,所有用户都离开了,过了设定的时间都没有业务,那么后面3个窗口就要关闭
🎈AbortPolicy()
package org.Test6;
import java.util.concurrent.*;
public class Demo01 {
public static void main(String[] args) {
//自定义线程池
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS, //超时等待时间
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
try {
for (int i = 1; i <= 10; i++) {
//使用线程池后,使用线程池来创建线程
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭线程池
threadPool.shutdown();
}
}
}
🎈DiscardPolicy()
package org.Test6;
import java.util.concurrent.*;
public class Demo01 {
public static void main(String[] args) {
//自定义线程池
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS, //超时等待时间
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardPolicy()
);
try {
for (int i = 1; i <= 10; i++) {
//使用线程池后,使用线程池来创建线程
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭线程池
threadPool.shutdown();
}
}
}
丢掉任务,但是不会抛出异常
🎈DiscardOldestPolicy()
package org.Test6;
import java.util.concurrent.*;
public class Demo01 {
public static void main(String[] args) {
//自定义线程池
ExecutorService threadPool = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS, //超时等待时间
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.DiscardOldestPolicy()
);
try {
for (int i = 1; i <= 10; i++) {
//使用线程池后,使用线程池来创建线程
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
//关闭线程池
threadPool.shutdown();
}
}
}
在技术的道路上,我们不断探索、不断前行,不断面对挑战、不断突破自我。科技的发展改变着世界,而我们作为技术人员,也在这个过程中书写着自己的篇章。让我们携手并进,共同努力,开创美好的未来!愿我们在科技的征途上不断奋进,创造出更加美好、更加智能的明天!