1. 线程池的概念
线程池:一个容纳多个线程的容器,容器中的线程可以重复使用,省去了频繁创建和销毁线程对象的操作。
线程池作用:
- 降低资源消耗,减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
- 提高响应速度,当任务到达时,如果有线程可以直接用,不会出现系统僵死。
- 提高线程的可管理性,如果无限制的创建线程,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
思想 : 提前把线程准备好,创建线程并不从系统申请,而是从池子里拿,用完放回线程池
创建线程就涉及到内核态和用户态
- 内核态:内核态是操作系统运行的状态,也叫做超级用户模式,此时的操作系统可以直接访问整个硬件,包括内存、CPU、外围设备等,执行系统级别的指令,如I/O操作、创建或结束一个进程等。
- 用户态:用户态是用户进程运行的状态,权限相对较低,用户进程只能访问自身的地址空间,无法直接访问内核数据和硬件设备,只能通过系统调用的方式,向操作系统请求服务,间接地进行一些系统级别的操作。
总结 : 内核处理的程序有很多,拖延时间,想要提升效率,我们应使用用户态
1.1 参数介绍
我们在Java的官方文档中,可以找到对线程池的介绍
如果把线程池比喻一个公司
corePoolSize 核心线程数 正式员工
maximumPoolSize 最大线程数量 正式员工+实习生
keepAliveTime 保持存活的时间 实习生存活时间(时间内不会被辞退)
TimeUnit 时间单位 ( s,分钟,ms)
拒接策略
AbortPolicy():以抛出异常的方式拒绝(默认的拒绝策略)
CallerRunsPolicy():让调用的线程来处理
DiscardOldestPolicy():丢弃时间最久的任务(先进先出)
DiscardPolicy():丢弃新来的任务
我们一般常用的创建线程池
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(10);
pool.submit(new Runnable() {
@Override
public void run() {
System.out.println("bit");
}
});
}
上面代码中,并未new 一个 ExecutorService,而是调用 Executor 中的静态方法完成构造,我们称为
"工厂模式"
那为什么,不能直接new 一个对象呢,大家都知道,调用构造方法,需要与类名相同,实现不同版本的构造,需要构成重载,参数类型和数量不同,特殊情况,方法名和参数类型,参数数量相等,就只能使用工厂模式来实现
class Point {
// 笛卡尔坐标系,构造点
public Point(double x, double y) { };
// 使用极坐标系,构造点
public Point(double r, double a) { };
// Error : 编译错误
}
工厂模式 :
class Point {
// 笛卡尔坐标系,构造点
public static Point makePointByXY(double x, double y) {
Point point = new Point();
point.setX(x);
point.setY(y);
return point;
}
// 极坐标系,构造点
public static Point makePointByRA(double r, double a) {
Point point = new Point();
point.setR(r);
point.setA(a);
return point;
}
}
Executors 创建线程池的几种方式 :
1.newFixedThreadPool: 创建固定线程数的线程池
2.newCachedThreadPool: 创建线程数目动态增长的线程池 .
3.newSingleThreadExecutor: 创建只包含单个线程的线程池 .
4.newScheduledThreadPool: 设定 延迟时间后执行命令,或者定期执行命令
最后自定义一个线程池
class MyPool{
//创建阻塞队列存放任务
private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
public void submit(Runnable runnable) throws InterruptedException {
queue.put(runnable);
}
// 实现线程池
public MyPool(int n){
for (int i = 0; i < n; i++) {
Thread t = new Thread(() -> {
while (true) {
try {
Runnable runnable = queue.take();
runnable.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
}
}
public class Test1 {
public static void main(String[] args) throws InterruptedException {
MyPool myPool = new MyPool(10);
for (int i = 0; i < 1000; i++) {
int number = i;
myPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("bit" + number);
}
});
}
}
}