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

金科科技 做网站今日新闻最新头条10条内容

金科科技 做网站,今日新闻最新头条10条内容,wordpress视频网站采集,可以访问国外网站的dns目录 线程池 为什么使用线程池 线程池的使用 工厂类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/wzjs/489316.html

相关文章:

  • 企业发展历程网站备案查询站长工具
  • 怎么提高网站seo优化关键字排名防控措施持续优化
  • 百度收录提交网站后多久收录房地产最新消息
  • 怎么做旅行网站关键词排名优化营销推广
  • 下载宝硬盘做网站广州百度推广电话
  • 创建站点如何做网站精准引流的网络推广
  • 专业企业建站价格深圳网络营销的公司哪家好
  • 搭建网站服务器教程宁德市委书记
  • 5ucms怎样做网站自适应培训课程网站
  • 服饰怎么做网站推广河源疫情最新通报
  • 营销型企业网站建设价格seo刷排名公司
  • 做网站 需要什么营业执照网销是做什么的
  • 淘宝客网站api关键字搜索引擎
  • 射阳做网站多少钱北京seo百科
  • 荆门市城乡建设管理局网站百度网盘app官网
  • 基础建设期刊南平网站seo
  • 网站开发合同协议最近一周的重大新闻
  • 辅助购卡网站怎么做网站seo快速优化技巧
  • 丰胸建设网站重庆百度竞价推广
  • 建筑网站资料排行榜西安seo关键词排名
  • 赛事竞猜网站开发seo优化官网
  • 四川网站建设多少钱保定seo排名优化
  • 百度h5为什么发布不了站内seo优化
  • 做网站需要拉多大的宽带nba实力榜最新排名
  • 西安有关做网站的公司有哪些免费的域名和网站
  • 做网站哪便宜弹窗广告最多的网站
  • 新河镇网站制作电商关键词工具
  • 任县企业做网站怎么做网站广告
  • 图怪兽作图神器下载关键词排名优化怎么样
  • 交通建设工程质量监督局网站怎么用网络推广业务