做网页和做网站的区别,开发小程序的注意事项,网站开发的账务处理,安康市劳务公司阿华代码#xff0c;不是逆风#xff0c;就是我疯#xff0c; 你们的点赞收藏是我前进最大的动力#xff01;#xff01;希望本文内容能够帮助到你#xff01; 目录 引入#xff1a;问题引入
一#xff1a;解决方案
1#xff1a;方案一——协程/纤程
#xff08;1… 阿华代码不是逆风就是我疯 你们的点赞收藏是我前进最大的动力希望本文内容能够帮助到你 目录 引入问题引入
一解决方案
1方案一——协程/纤程
1本质
2方案二——线程池
1本质
2优缺点
3解释高效的原因
二ThreadPoolExecutor标准库线程池
1Java库中找
2构造方法
1核心线程数
2最大线程数
3保持存活时间
4时间单位
5工作任务
6线程工厂
①工厂模式
7拒绝策略面试高频
①中止策略
②甩锅策略
③喜新厌旧
④忠贞不渝
三Executors工厂类
1.newFixedThreadPool可以设定固定线程数目
2submit添加任务
编辑3线程池中线程数量问题
1前引
2线程任务的分类
①CPU密集型任务
②IO密集型任务
3分情况讨论
四通过代码实现简单的线程池
1思路
2代码示例 引入问题引入
在之前的学习中我们了解到为了降低频繁创建和销毁进程所带来的巨大开销我们引入了轻量级进程的概念线程
现在若线程的数量进一步提升那么线程的频繁创建和销毁所带来的资源消耗我们也不能忽视了
所以我们进行优化引入了“池”的概念这里有许多种类的池线程池数据库连接池进程池......提前把需要用到的对象准备好用完的 对象也不要直接扔掉放到池子中以便下次使用
一解决方案
1方案一——协程/纤程
注可以理解为轻量级线程
1本质
通过用户态代码进行调度不靠系统内核的调度器调度节省了调度的开销
注在java21中“虚拟线程”就是这个意思。 在用户代码中协程是基于线程进行封装的。 go是比较早支持协程的因为语法简单就火了
2方案二——线程池
1本质
提前创建好线程需要用的时候直接从池子里拿出来用用完了也不要释放而是返还回池子中。
2优缺点
①优点节省了创建和销毁线程带来的资源消耗更高效
②缺点占用了内存空间
3解释高效的原因
从线程池里获取线程是在用户态代码中进行调度是可控的高效的
从操作系统中获取线程是在系统内核中进行完成的不可控低效。 二ThreadPoolExecutor标准库线程池
1Java库中找
注打开网站Overview (Java Platform SE 8 )找到对应的包和class类 2构造方法 我们直接看带有7个参数的构造方法 1核心线程数 int corePoolSize core核心pool池siz大小 2最大线程数 int maximumPoolSize 核心线程可以理解为公司的正式员工不能轻易裁掉 普通线程可以理解为公司的实习生裁掉比较容易 最大线程数 核心线程数 普通线程数 3保持存活时间 long keepAliveTime 4时间单位 TimeUnit unit 单位sminhour....... 普通线程能空闲的最大时间超过空闲时间限制就会被移除线程池 还是用上述例子举例实习生不能说开就开假定摸鱼时间限制为1个小时只要实习生摸鱼的时间小于1个小时就不会被开超过就被开 5工作任务
BlockingQueueRunnable workQueue
与定时器上篇文章相似线程池可以持有多个任务
Runnable用来描述任务的主体
也可以写PriorityQueue优先级队列
6线程工厂
ThreadFactory threadFactory
①工厂模式
通过“工厂类”类里面的不一定是静态的方法对方法内部的new对象进行构造完成对象的初始化相当于给构造方法外面在套上一层方法——套娃“封装” 7拒绝策略面试高频
RejectedExecutionHandler handler——
execution执行handler操作者
问题试想线程池中有一个阻塞队列存放的线程数目已经达到最大荣达这个时候还往里面存放那么线程池会怎么办 ①中止策略
.AbortPolicy ——
如果硬要在加新任务的话线程池我吃柠檬lz新旧任务都不干了抛出异常 ②甩锅策略
.CallerRunsPolicy——
线程池让交代给我这个任务的人自己完成这个线程我才不干
③喜新厌旧
.DiscardOldestPolicy——
discard丢弃
线程池抛弃池中呆的最久最老的一个线程迎接新欢喜新厌旧
④忠贞不渝
.DiscardPolicy——
丢弃要新添加的任务继续我行我素执行线程池中本来就有的任务
三Executors工厂类
因为ThreadPoolExecutor使用起来较为复杂所以标准库中就封装了一下提供了Executors这个版本工厂类在内部把ThreadPoolExecutor创建好了并且设置了不同的参数
1.newFixedThreadPool可以设定固定线程数目 2submit添加任务
package thread;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadDemon34 {public static void main(String[] args) {ExecutorService service Executors.newFixedThreadPool(4);service.submit(new Runnable(){Overridepublic void run() {System.out.println(执行线程池中第一个任务);}});}
}返回值类型点进去
3线程池中线程数量问题
1前引
我们知道线程的运行效率跟cpu的逻辑核心数直接相关假设cpu的逻辑核心数为N那线程的数量该是多少合适2N1.5NN..........
2线程任务的分类
①CPU密集型任务
线程大部分时间都在CPU上运行计算
②IO密集型任务
大部分时间都在等待IOinputoutput。例如Scanner读取用户的输入
3分情况讨论
到底在线程池中添加多少线程数量合适呢
如果线程多为CPU类型的那线程数目尽量不要超过N
如果线程多为IO类型的那线程数目就可以远远超过N
但是具体开发肯定是需要我们多次测试通过观察系统资源消耗来找出最合适的添加数目的。
四通过代码实现简单的线程池
1思路
大逻辑其实就是把创建的任务提交上去再把任务取出来在run执行就可以了就是这么简单
我们用到的IDEA自带的顺序表阻塞队列BlockingQueue都其实是一个工具罢了~~
2代码示例
package thread;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;/*** Created with IntelliJ IDEA.* Description:* User: Hua YY* Date: 2024-09-27* Time: 16:48*/class MyThreadPoolExecutor{//2:创建一个顺序表来接收创建的线程private ListThread threadList new ArrayList();//4创建一个容量合适的阻塞队列private BlockingQueueRunnable queue new ArrayBlockingQueue(1000);//1:通过一个循环n的值来控制产生的线程的数量public MyThreadPoolExecutor(int n){for (int i 0; i n; i) {Thread t new Thread(()-{//6:把要做的任务从任务队列中不停地取出来并且执行while(true){try {//带有阻塞的take取出元素Runnable runnable queue.take();runnable.run();} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();//3:threadList.add(t);}}//5:提交runnable到队列里面去public void submit(Runnable runnable) throws InterruptedException {queue.put(runnable);}
}
public class ThreadDemon35 {//大逻辑其实就是把创建的任务提交上去再把任务取出来在run执行就可以了就是这么简单public static void main(String[] args) throws InterruptedException {MyThreadPoolExecutor executor new MyThreadPoolExecutor(4);for (int i 0 ; i 1000 ; i){//变量捕获int n i;executor.submit(new Runnable() {Overridepublic void run() {System.out.println(执行任务 n 当前线程为 Thread.currentThread().getName());}});}}
}