当前位置:网站首页>实现线程池
实现线程池
2022-07-31 09:16:00 【Master_hl】
1.线程池是什么?
线程池,字面意思来说,有点类似与我们的字符串常量池,数据库连接池等等。
1.1 为啥要引入线程池这一概念呢??
这得从引入线程说起,,
进程本身已经能做到 并发编程了,为啥还要有线程??进程太重量了,创建和销毁成本都比较高(需要申请、释放资源),而线程就是针对上述问题的优化(同一个进程中的线程共用同一组系统资源)
虽然如此,但是在更频繁的创建、释放资源的场景下,线程也有点扛不住了!!
所以,进一步优化,就引入了线程池。线程池存在的目的,就是为了让程序猿不必创建新的线程,直接使用已有的线程完成想要进行的工作即可!!
【线程池解决问题的思路】
把线程创建好了之后,放到池子里,需要使用线程,就直接从池子里取,而不是通过系统来创建。当线程用完了,又放回池子里,而不是通过系统来销毁!!
1.2 为什么把线程放到池子里,从池子里取线程就要比从系统这里创建线程效率高呢??
1.从池子里取,是纯用户态操作。
2.通过系统来创建,涉及到内核操作。
而我们通常认为,牵扯到内核态操作,就要比纯用户态的操作更低效!!结合下图场景理解
2.标准库中的线程池
1.使用 Executors.newFixedThreadPool(10) 能创建出固定包含 10 个线程的线程池.
2.返回值类型为 ExecutorService3.通过 ExecutorService.submit 可以注册一个任务到线程池中.
public static void main(String[] args) {
ExecutorService threadPool = Executors.newFixedThreadPool(10);
for(int i = 0; i < 100; i++) {
threadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
});
}
}
注意这行代码:
ExecutorService threadPool = Executors.newFixedThreadPool(10);
newFixedThreadPool 是 Executors 类的一个静态方法,像这种借助静态方法创建实例,这样的方法,称为"工厂方法",对应的设计模式,就叫做"工厂模式"。
通常情况下,创建对象,是借助 new ,调用构造方法来实现的。但是 Java 里面的构造方法,有诸多限制,在很多时候不方便使用,因此就需要给构造方法再包装一层,外层起到包装作用的方法就是工厂方法!!
为什么构造方法有时候不方便使用??
构造方法的限制在于,当前构造方法的名字务必是和类名一样。要想实现不同版本的构造,就得通过重载,但是重载又要求参数类型和个数不同。当我们的场景刚好是参数类型相同且参数个数相同的时候,重载就行不通了!!请看以下例子:
当我需要用构造方表示两个点:一个是笛卡尔坐标系,构造点;一个是极坐标系构造点。
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: 设定 延迟时间后执行命令,或者定期执行命令. 是进阶版的Timer.
Executors 里面的各种工厂方法,其实都是针对 ThreadPoolExecutor 这个类进行了 new 并且闯入不同风格的参数,来达到构造不同种类线程池的目标!!
3.实现线程池
class MyThreadPool {
// 这个队列就是 "任务队列" 把当前线程要完成的任务都放入到这个队列中
// 再由线程池内部的工作线程负责完成它们!!
private BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>();
// 核心方法,往线程池里插入任务
public void submit(Runnable runnable) {
try {
queue.put(runnable);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// n : 设定线程池里有几个线程
public MyThreadPool(int n) {
// 构造方法中就需要创建一些线程,让这些线程负责执行上述插入的任务
for(int i = 0; i < n; i++) {
Thread t = new Thread(() -> {
while(!Thread.currentThread().isInterrupted()) {
try {
// 取出任务,直接执行
Runnable runnable = queue.take();
runnable.run();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
}
}
}
public class TestDemo3 {
public static void main(String[] args) {
// 10 个线程一起执行 100 个任务
MyThreadPool myThreadPool = new MyThreadPool(10);
for(int i = 0; i < 100; i++) {
myThreadPool.submit(new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
});
}
}
}
线程池的实现相比于定时器,要简单太多了!!
【基本步骤】
1.核心操作为 submit,将任务加入线程池中;
2.使用一个 BlockingQueue 组织所有的任务;
3.每个线程,不停的从 BlockingQueue 中取任务并执行即可。
本篇博客就到这里了,谢谢观看!!
边栏推荐
猜你喜欢
loadrunner脚本--添加检查点
【TCP/IP】Network Model
js right dot single page scrolling introduction page
js implements the 2020 New Year's Day countdown bulletin board
期刊会议排名、信息检索网站推荐以及IEEE Latex模板下载
【Unity】编辑器扩展-03-拓展Inspector视图
一次Spark SQL线上问题排查和定位
Doraemon teach you forwarded and redirect page
服务器上解压文件时提示“gzip: stdin: not in gzip format,tar: Child returned status 1,tar: Error is not recovera“
HTC官方RUU固件提取刷机包rom.zip以及RUU解密教程
随机推荐
数字加分隔符
(selenium)Service geckodriver unexpectedly exited. Status code was: 64
通过栗子来学习MySQL高级知识点(学习,复习,面试都可)
状态机动态规划之股票问题总结
mysql 数据去重的三种方式[实战]
混合型界面:对话式UI的未来
【RISC-V】risc-v架构学习笔记(架构初学)
A brief introduction to the SSM framework
PyQt5快速开发与实战 9.4 Matplotlib在PyQt中的应用
Define event types in Splunk Web
How to restore data using mysql binlog
Progressive Web App(PWA)
六、MFC文档类(单文档和多文档)
Kotlin—基本语法(二)
js右侧圆点单页滚动介绍页面
A Spark SQL online problem troubleshooting and positioning
Canvas particles change various shapes js special effects
ScheduledExecutorService - 定时周期执行任务
MySQL 的几种碎片整理方案总结(解决delete大量数据后空间不释放的问题)
Linux 创建mysql数据库并创建账号密码