文章目录
一、线程池是什么
线程池就是提前把线程准备好,创建线程不是直接从系统中申请了,而是从池子那个那,用完了再还给池子。
为什么要有线程池呢??
虽然我们说线程是轻量化的,但是如果数量特别多,而且频繁创建,那么这个开销也是不可忽视的~ 线程池的最大好处就是减少每次启动,销毁线程的损耗~
二、为什么从线程池里拿线程就比从系统创建快呢?
我们从线程池拿线程,就是纯粹的用户态操作~
从系统创建线程,就要设计到用户态和内核态的转换了~
举例说明:
假如你要去复印店复印文件~有很多人都在,此时你有两种选择,
第一张是找老板,告诉他我要复印什么,老板说知道了,然后就去了,但是老板还有很多其他的事情,他可能不是第一时间就给你打印,可能是先给先来的打印了,或者上了个厕所~(此时的老板就是内核)
第二种是:你自己去复印的电脑哪里自己打印,你自己就只有一个任务,就直接给自己打印就完事 了~(用户态) 所以说线程池拿取线程和销毁都比直接从系统操作要快~
三、简单使用库里提供的线程池~
这样就可以使用线程池来进行线程的创建和销毁~
那么这里为什么不是直接new一个线程池呢??
这就是构造方法留下的坑了
我们知道在JAVA里,有构造方法来描述对象,并初始化,我们可以通过重载来实现一个多个多个描述,但是如果参数完全相同就无法构成重载,万一你两种描述的参数就是一模一样的,这就很蛋疼了~这就没办法了,所以就只能使用工厂模式(专门创建一个类来构造方法)来解决~
四、Executors 创建线程池的几种方式
1.newFixedThreadPool:创建固定线程数的线程池(输入十个就是创建十个线程)
2.newCachedThreadPool: 创建线程数动态增长的线程池~
3.newSingleThreadExecutor:创建只包含一个线程的线程池
五、线程池的参数介绍
这是JAVA官方给出的线程池参数:
1.corePoolSize:核心线程数 (真正的核心有几个线程)
六、模拟实现线程池
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
class MyThreadpool{
private BlockingDeque<Runnable> queue=new LinkedBlockingDeque<>(); //阻塞队列
public void submit(Runnable runnable) throws InterruptedException {
queue.put(runnable); //把任务放到阻塞队列
}
public MyThreadpool(int n){ //模拟固定线程数量的线程池
for (int i = 0; i <n; i++) {
Thread t=new Thread(()->{
try {
while (true) { //要让线程不停的取任务
Runnable runnable = queue.take();
runnable.run();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t.start();
}
}
}
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
MyThreadpool pool=new MyThreadpool(10);
for (int i = 0; i <1000; i++) {
int number=i;
pool.submit(new Runnable() {
@Override
public void run() {
System.out.println("hello"+number);
}
});
}
}
}
线程就会执行打印一千次(并发执行)~
总结
介绍了 线程池的基本参数,如何使用Executors 创建线程池,模拟实现线程池,还有很多不足之处,老铁们多多指教~