当前位置: 首页 > news >正文

江西移动网站建站推广外包

江西移动网站,建站推广外包,北京好的做网站公司,悦然wordpress建站服务目录 线程池 为什么使用线程池 线程池的使用 工厂类Executors(工厂模式) submit 实现一个线程池 线程池 为什么使用线程池 在前面我们都是通过new Thread() 来创建线程的,虽然在java中对线程的创建、中断、销毁、等值等功能提供了支持…

目录

线程池

为什么使用线程池

线程池的使用

工厂类Executors(工厂模式)

submit 

实现一个线程池


线程池

为什么使用线程池

在前面我们都是通过new Thread() 来创建线程的,虽然在java中对线程的创建、中断、销毁、等值等功能提供了支持,一个线程的创建和销毁虽然消耗虽然小,但从操作系统角度来看,如果我们频繁的创建和销毁线程,是需要大量的时间和资源的,那么有没有什么开销更小的方法?

第一种是协程,它可以说是轻量级线程,但是java很少用,多用于go和python。

第二种是线程池,java中多用线程池去解决频繁的创建和销毁线程问题。

那么为啥引入线程池就能够提升效率呢?

1.直接创建/销毁线程,是需要在用户态+内核态配合完成的工作,对于线程池,只需要在用户态即可,不需要内核态的配合,这样开销就更小

2.等线程用完之后,线程池不会销毁该线程,而是让其阻塞,等下次用的时候会再次利用它,所以不用频繁的进行创建和销毁。

线程池最核心的设计思路:复用线程,平摊线程的创建与销毁的开销代价

线程池的使用

java 提供了多种方式来创建线程池,主要通过Executors(执行者)工厂类或直接使ThreadPoolExecutor类来完成

工厂类Executors(工厂模式)

使用Executors工厂类:

newFixedThreadPool(int nThreads):创建一个固定大小的线程池,线程数量由nThreads参数确定。
newCachedThreadPool():创建一个线程数量为动态的线程池,线程数量会根据任务数量动态变化,当长时间没有新任务时,空闲线程会被终止。

newSingleThreadExecutor():创建一个单线程的线程池,它只会创建一个线程来执行任务。
newScheduledThreadPool(int corePoolSize):创建一个可以安排任务的线程池,可以指定延迟执行任务或定期执行任务。

后面两个我们用的都不多,主要是用前面两个

下面是使用代码:

​
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {// 创建一个固定大小的线程池ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);// 创建一个可缓存的线程池(线程数量动态调整)ExecutorService cachedThreadPool = Executors.newCachedThreadPool();}
}

这代码我们有个疑点,我们并没有new一个对象,那我们是怎么创建出来对象的呢?

这个问题涉及到工厂模式这种设计模式:

工厂模式是一种常用的设计模式,用于封装对象的创建逻辑。它通过使用方法来创建对象(new在方法内部),而不是直接使用 new 关键字实例化对象。这样可以将对象的创建逻辑与使用逻辑解耦,提高代码的可维护性和可扩展性。

这里就是用方法创建出对象,所以涉及到了工厂模式

ThreadPoolExecutor类(直接new)
对于刚才讲的 Executors 本质上是 ThreadPoolExecutor 类的封装.         

而对于ThreadPoolExecutor类本身我们提供了更多的可选参数, 可以进一步细化线程池行为的设定. 

如下图是 ThreadPoolExecutor类的构造方法:

核心线程数(corePoolSize):线程池中始终保持的线程数量。这是不会被销毁的。

最大线程数(maximumPoolSize):线程池中允许的最大线程数量。这种一般涉及到刚才的动态线程池,如果任务多了则创建一些线程,多了的话过了一段时间则会销毁,但核心线程数不变。

空闲线程存活时间(keepAliveTime):当线程池中的线程数量超过核心线程数时,空闲线程的存活时间。

任务队列(workQueue):其为阻塞队列,用于存储等待执行的任务。要记住,当我们创建线程池时,系统也会同时自动创建一个阻塞队列去存储等待执行的任务,这样效率就更高。

线程工厂(threadFactory):线程工厂是一个用于创建线程的工具类或接口,它允许用户自定义线程的创建逻辑,开发者可以控制线程的名称、优先级、异常处理等属性,从而更好地管理线程资源。

拒绝策略(handler):当线程池已满且阻塞队列也已满时,新任务的处理策略。

下面重点讲述一下拒绝策略:

  • AbortPolicy:直接抛出 RejectedExecutionException 异常。(当导员给我一个任务“统计班级成员中团员个数‘’,但是我现在已经课很多了,我一下子就哭了出来)这个就相当于直接抛异常
  • CallerRunsPolicy:由提交任务的线程直接执行任务。(我直接给导员说,我没空,导员最后只能自己做了)
  • DiscardPolicy:直接丢弃任务,不抛出异常。(导员一听我没空,就直接说,好!那我也不统计了,随便来了)
  • DiscardOldestPolicy:丢弃队列中最老的任务,然后尝试提交新任务。(我听到导员的任务的时候,我选择放弃我最早出现的一节课去帮导员完成任务)

下面是其创建代码 

 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2,  // 核心线程数4,  // 最大线程数60,  // 空闲线程存活时间TimeUnit.SECONDS,  // 时间单位new ArrayBlockingQueue<>(10),  // 任务队列,容量为 10Executors.defaultThreadFactory(),  // 线程工厂new ThreadPoolExecutor.AbortPolicy()  // 拒绝策略);

总结一下:

  • 工厂模式创建线程:适合简单的线程池创建场景,代码简单,但灵活性有限。

  • 构造方法创建线程:适合需要灵活配置线程池属性的场景,通过自定义线程池,可以更好地管理线程资源,提高代码的可维护性和可扩展性。

submit 

 通过线程池.submit(继承runable的类的对象) 可以提交一个任务到线程池中执行.

ExecutorService pool = Executors.newFixedThreadPool(10);
pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello");}
});
实现一个线程池

 这里就直接上代码了,不多说,重点还是使用线程池,不是实现线程池。

/*** 自定义线程池执行器类* 该类通过实现一个具有固定大小的线程池和一个阻塞队列来管理线程,用于异步执行任务*/
class MyThreadPoolExecutor {// 创建阻塞队列,用于存放待执行的任务// 队列大小设为1000,用于控制并发任务的数量,避免过多任务导致资源耗尽BlockingQueue<Runnable>  blockingQueue=new ArrayBlockingQueue<>(1000);/*** 构造函数,初始化线程池* 创建一个线程,该线程循环从阻塞队列中取任务并执行* 这个线程是线程池中的工作线程,负责执行提交的任务*/public MyThreadPoolExecutor(int n) {for (int i = 1; i <= n; i++) {Thread t = new Thread(() -> {// 无限循环,确保线程池可以持续处理任务,直到程序中断或阻塞队列被清空while (true) {try {// 从阻塞队列中取出一个任务,如果队列为空,则线程被阻塞,直到有任务放入队列Runnable task = blockingQueue.take();// 执行取出的任务task.run();} catch (InterruptedException e) {// 如果线程在等待状态时被中断,抛出运行时异常// 这通常会导致程序异常终止throw new RuntimeException(e);}}});// 启动线程池中的工作线程t.start();}}/*** 提交一个任务到线程池* @param task 需要被执行的任务*            任务被放入阻塞队列中,随后由线程池中的工作线程执行*/public void submit(Runnable task){// 将任务放入阻塞队列,如果队列已满,则操作会阻塞,直到有空间可用blockingQueue.offer(task);}
}
class DemoTest1{public static void main(String[] args) throws InterruptedException {MyThreadPoolExecutor ex=new MyThreadPoolExecutor(4);for(int i=0;i<100;i++) {int id = i;ex.submit(()->{System.out.println(Thread.currentThread().getName()+"  任务:"+id);});}}
}

多线程基础知识点到这里就告一段路了,接下来我们将学习多线程(进阶)这部分是主要讲面试中经典题,频繁的题

http://www.dtcms.com/a/512305.html

相关文章:

  • 张家口网站建设zjktao温州公司网址公司
  • Cef笔记:Cef消息循环的集成
  • 第十六篇:Lambda表达式:匿名函数对象的艺术
  • 织梦cms通用蓝白简介大气企业网站环保科技公司源码汕头网站制作全过程
  • xss-labs pass-06
  • 解决selenium提示chrome版本过低问题
  • 重庆做网站电话深圳做装修网站费用多少
  • 做网站的免费空间商品房交易网
  • 鸡蛋质量识别数据集,可识别染血的鸡蛋,棕色鸡蛋,钙沉积鸡蛋,污垢染色的鸡蛋,白鸡蛋,平均正确识别率可达89%,支持yolo, json, xml格式的标注
  • YOLOv4简单基础学习
  • 网站的域名每年都要续费南通网络科技有限公司
  • LLAMA-Factory Qwen3-1.7b模型微调
  • PageHelper 分页框架查询总数 SQL 错误解决方案:从源码逻辑到版本影响(含实验验证)
  • NExF——建立3D空间上的曝光场辅助重建
  • 网站建设公司 合肥影视后期制作培训机构全国排名
  • 审计 jenkins获取构建历史,生成excel
  • 【能源与流程工业案例】KBC借助TeeChart 打造工业级数据可视化平台
  • 网站站点的建立wordpress 清单 主题
  • 苏州市建设交易中心网站wordpress 插件 重置密码
  • Linux 网络协议栈数据流跟踪-静态路由demo
  • 【C++】STL容器--list的模拟实现
  • 再次使用xca软件生成自签证书的补充说明
  • 第2章 数据库系统的核心--数据模型
  • 计算机组成基础
  • 迅投xtquant获取股票对应的申万行业
  • 百度seo网站在线诊断小程序开发平台需要网站吗
  • 网站开发用什么书什么网站可以做行测
  • 柳州做网站公司网站建设实施方案
  • excel拆分和合并代码的思路整合和工具打包
  • 信刻——安全生产音视频录音录像自动刻录备份归档管理系统