? 作者:小胡_不糊涂
🌱 作者主页:小胡_不糊涂的个人主页
📀 收录专栏:JavaEE
💖 持续更文,关注博主少走弯路,谢谢大家支持 💖
想象这么?个场景:
在学校附近新开了?家快递店,?板很精明,想到?个与众不同的办法来经营。店?没有雇?,?是每次有业务来了,就现场找?名同学过来把快递送了,然后解雇同学。这个类?我们平时来?个任务,启动?个线程进?处理的模式。
很快?板发现问题来了,每次招聘 + 解雇同学的成本还是?常?的。?板还是很善于变通的,知道了为什么?家都要雇?了,所以指定了?个指标,公司业务?员会扩张到3个?,但还是随着业务逐步雇?。于是再有业务来了,?板就看,如果现在公司还没3个?,就雇?个?去送快递,否则只是把业务记下来,等着3个快递?员空闲的时候去处理。这个就是我们要带出的线程池的模式。
线程池最?的好处就是减少每次启动、销毁线程的损耗。
在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 创建线程池的几种?式:
ThreadPoolExecutor 提供了更多的可选参数,可以进?步细化线程池?为的设定:
主要思路:
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());
}
});
}
}
}
多个线程之间的执行顺序是不确定的,某个线程取到任务也并非是立即就执行,就会产生无序的结果。但此处这些线程都是等价的。