线程池实现
2023-12-24 17:46:55
? 作者:小胡_不糊涂
🌱 作者主页:小胡_不糊涂的个人主页
📀 收录专栏:JavaEE
💖 持续更文,关注博主少走弯路,谢谢大家支持 💖
1. 什么是线程池
想象这么?个场景:
在学校附近新开了?家快递店,?板很精明,想到?个与众不同的办法来经营。店?没有雇?,?是每次有业务来了,就现场找?名同学过来把快递送了,然后解雇同学。这个类?我们平时来?个任务,启动?个线程进?处理的模式。
很快?板发现问题来了,每次招聘 + 解雇同学的成本还是?常?的。?板还是很善于变通的,知道了为什么?家都要雇?了,所以指定了?个指标,公司业务?员会扩张到3个?,但还是随着业务逐步雇?。于是再有业务来了,?板就看,如果现在公司还没3个?,就雇?个?去送快递,否则只是把业务记下来,等着3个快递?员空闲的时候去处理。这个就是我们要带出的线程池的模式。
线程池最?的好处就是减少每次启动、销毁线程的损耗。
2. 标准库中的线程池
在Java中可以使?Executors.newFixedThreadPool(10) 能创建出固定包含10个线程的线程池。返回值类型为 ExecutorService,然后通过 ExecutorService.submit 可以注册?个任务到线程池中。
public static void main(String[] args) {
ExecutorService service=Executors.newFixedThreadPool(10);
service.submit(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
});
}
Executors 创建线程池的几种?式:
- newFixedThreadPool:创建固定线程数的线程池
- newCachedThreadPool:创建线程数?动态增?的线程池
- newSingleThreadExecutor:创建只包含单个线程的线程池
- newScheduledThreadPool:设定延迟时间后执?命令,或者定期执?命令。是进阶版的 Timer
Executors 本质上是 ThreadPoolExecutor 类的封装
ThreadPoolExecutor 提供了更多的可选参数,可以进?步细化线程池?为的设定:
- corePoolSize:正式员?的数量。(正式员?,?旦录?,永不辞退)
- maximumPoolSize:正式员? + 临时?的数?。(临时?:?段时间不?活,就被辞退)
- keepAliveTime:临时?允许的空闲时间
- unit:keepaliveTime 的时间单位
- workQueue:传递任务的阻塞队列
- threadFactory:创建线程的??,参与具体的创建线程?作。通过不同线程??创建出的线程相当于对?些属性进?了不同的初始化设置
- RejectedExecutionHandler:拒绝策略,如果任务量超出公司的负荷了接下来怎么处理
3. 线程池模拟实现
主要思路:
1.提供构造方法,指定创建多少个线程
2.在构造方法中,把这些线程都创建好
3.有一个阻塞队列,能够持有要执行的任务
4.提供submit方法,可以添加新的任务
class MyThreadPoolExecutor{
private List<Thread> threadList=new ArrayList<>();//保存产生的线程
private BlockingQueue<Runnable> queue=new ArrayBlockingQueue<>(1000);//保存任务的队列
//通过n指定创建多少个线程
public MyThreadPoolExecutor(int n) {
for (int i = 0; i < n; i++) {
//取出任务并执行
Thread t = new Thread(() -> {
while(true){
try {
Runnable runnable=queue.take();///如果队列为空,take就会阻塞
runnable.run();//取出一个执行一个
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
threadList.add(t);
}
}
//把任务传到队列中
public void submit(Runnable runnable) throws InterruptedException {
queue.put(runnable);
}
}
测试类:
public class TestDemo9 {
//public static volatile int i=0;
public static void main(String[] args) throws InterruptedException {
MyThreadPoolExecutor executor = new MyThreadPoolExecutor(4);
for (int i = 0; i < 10; i++) {
int n = i;//防止变量捕获(不可以是一直变化的值)-->volatile
executor.submit(new Runnable() {
@Override
public void run() {
System.out.println("执行任务" + n + "当前任务的线程为:" + Thread.currentThread().getName());
}
});
}
}
}
多个线程之间的执行顺序是不确定的,某个线程取到任务也并非是立即就执行,就会产生无序的结果。但此处这些线程都是等价的。
文章来源:https://blog.csdn.net/iLoyo_/article/details/135181511
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!