异步模式之工作线程

news/2025/2/13 0:15:14/

目录

定义

饥饿

创建多少线程池合适

CPU 密集型运算

I/O 密集型运算


定义

让有限的工作线程(Worker Thread)来轮流异步处理无限多的任务。也可以将其归类为分工模式,它的典型实现 就是线程池,也体现了经典设计模式中的享元模式。

例如,海底捞的服务员(线程),轮流处理每位客人的点餐(任务),如果为每位客人都配一名专属的服务员,那 么成本就太高了(对比另一种多线程设计模式:Thread-Per-Message)

注意,不同任务类型应该使用不同的线程池,这样能够避免饥饿,并能提升效率

例如,如果一个餐馆的工人既要招呼客人(任务类型A),又要到后厨做菜(任务类型B)显然效率不咋地,分成 服务员(线程池A)与厨师(线程池B)更为合理,当然你能想到更细致的分工

饥饿

固定大小线程池会有饥饿现象

两个工人是同一个线程池中的两个线程

他们要做的事情是:为客人点餐和到后厨做菜,这是两个阶段的工作

  • 客人点餐:必须先点完餐,等菜做好,上菜,在此期间处理点餐的工人必须等待
  • 后厨做菜:没啥说的,做就是了

比如工人A 处理了点餐任务,接下来它要等着 工人B 把菜做好,然后上菜,他俩也配合的蛮好

但现在同时来了两个客人,这个时候工人A 和工人B 都去处理点餐了,这时没人做饭了,饥饿

public class Test {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(2);executorService.submit(()->{System.out.println("点餐中...");Future<String> future = executorService.submit(() -> {return "宫保鸡丁1";});try {String s = future.get();System.out.println("上菜"+s);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}});executorService.submit(()->{System.out.println("点餐中...");Future<String> future = executorService.submit(() -> {return "宫保鸡丁2";});try {String s = future.get();System.out.println("上菜"+s);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}});}
}

运行结果如下:

点餐中...
点餐中...
上菜宫保鸡丁2
上菜宫保鸡丁1

 如果修改核心线程为3,即修改代码中

ExecutorService executorService = Executors.newFixedThreadPool(3);

 则运行结果如下:

点餐中...
点餐中...
上菜宫保鸡丁2
上菜宫保鸡丁1

解决方法可以增加线程池的大小,不过不是根本解决方案,还是前面提到的,不同的任务类型,采用不同的线程池,例如:

public class Test {public static void main(String[] args) {ExecutorService orderExecutorService = Executors.newFixedThreadPool(1);ExecutorService cookExecutorService = Executors.newFixedThreadPool(1);orderExecutorService.submit(()->{System.out.println("点餐中...");Future<String> future = cookExecutorService.submit(() -> {return "宫保鸡丁1";});try {String s = future.get();System.out.println("上菜"+s);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}});orderExecutorService.submit(()->{System.out.println("点餐中...");Future<String> future = cookExecutorService.submit(() -> {return "宫保鸡丁2";});try {String s = future.get();System.out.println("上菜"+s);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}});}
}

运行结果如下:

 点餐中...
上菜宫保鸡丁1
点餐中...
上菜宫保鸡丁2

创建多少线程池合适

线程池的大小应根据具体的应用场景和系统需求来确定。以下是一些建议供参考:

  1. 考虑系统资源:线程池的大小应该与系统可用的资源相匹配。如果将线程池的大小设置得太大,会消耗过多的系统内存和CPU资源,导致系统性能下降;如果将线程池的大小设置得太小,可能无法充分利用系统资源,导致任务排队等待执行。

  2. 考虑任务类型:不同类型的任务对线程池的需求量不同。如果任务是CPU密集型(计算密集型),即任务在执行过程中主要消耗CPU资源,那么线程池的大小可以设置与CPU核心数相等或略大一些;如果任务是IO密集型(输入输出密集型),即任务在执行过程中主要消耗IO操作(如网络请求、文件读写等),那么线程池的大小通常可以设置较大,以便充分利用系统的IO能力。

  3. 考虑任务的响应时间:如果任务对响应时间要求较高,即需要快速响应用户请求,那么可以适当增加线程池的大小,以提高并发能力和响应速度。

  4. 考虑任务排队策略:线程池的大小还应考虑任务排队的策略。如果线程池使用有界队列作为任务缓冲区,当任务数量过多时,超出队列容量的任务将被拒绝执行;如果使用无界队列作为任务缓冲区,则线程池大小可以设置较大,以允许更多的任务排队等待执行。

总之,确定线程池大小需要综合考虑系统资源、任务类型、响应时间和任务排队策略等因素,并进行实际的性能测试和调优。根据实际情况不断调整线程池的大小,以达到最佳的性能和资源利用率。

CPU 密集型运算

通常采用 cpu 核数 + 1 能够实现最优的 CPU 利用率,+1 是保证当线程由于页缺失故障(操作系统)或其它原因 导致暂停时,额外的这个线程就能顶上去,保证 CPU 时钟周期不被浪费

I/O 密集型运算

CPU 不总是处于繁忙状态,例如,当你执行业务计算时,这时候会使用 CPU 资源,但当你执行 I/O 操作时、远程RPC 调用时,包括进行数据库操作时,这时候 CPU 就闲下来了,你可以利用多线程提高它的利用率。

经验公式如下

线程数 = 核数 * 期望 CPU 利用率 * 总时间(CPU计算时间+等待时间) / CPU 计算时间

例如 4 核 CPU 计算时间是 50% ,其它等待时间是 50%,期望 cpu 被 100% 利用,套用公式

4 * 100% * 100% / 50% = 8

例如 4 核 CPU 计算时间是 10% ,其它等待时间是 90%,期望 cpu 被 100% 利用,套用公式

4 * 100% * 100% / 10% = 40


http://www.ppmy.cn/news/529451.html

相关文章

fontForge开源字体定制工具

最近在工作中有一个小插曲。web后台使用的文字渲染插件无法对字体加粗&#xff0c;不巧的是&#xff0c;这个插件已经停止更新了&#xff0c;因此这个bug无法解决&#xff0c; 所以让我用qt实现这个插件的功能&#xff08;没错&#xff0c;就是为了一个加粗的功能重写整个插件&…

CSS入门六:字体样式;字体(楷体、隶书等),斜体,文字加粗,字体大小;

1.字体样式 下面四个&#xff0c;font-family和font-size先前已经接触过了&#xff1b;这篇博客的核心内容就是&#xff0c;italic和bold两个&#xff1b; ● 2.font-style&#xff1a; italic&#xff1a;斜体&#xff0c;对于大多数文字都可以实现倾斜效果&#xff1b;其本质…

竞价点击辅助工具

介绍&#xff1a; 注意&#xff1a;点击百度这版本目前无效&#xff0c;此版本仅供免费学习使用&#xff01; 1。 首先在测试文本添加关键词&#xff0c;一行一个&#xff0c;例如&#xff1a;鲜花河北鲜花店鲜花店哪家好2.然后在目录中找到&#xff1a;url文本&#xff0c;添…

windows辅助工具下载地址

这里提供window辅助工具下载&#xff1a;https://docs.microsoft.com/zh-cn/sysinternals/downloads/ 例如查看TCP连接情况可以使用TCPViewer

Windows提权辅助工具

一、在线网址 https://i.hacking8.com/tiquan 二、使用方法 1、通过systeminfo命令获取信息&#xff0c;并导入到一个txt文件 systeminfo >1.txt 2、将内容复制到网页&#xff0c;点击查询 3、查询可利用的漏洞 禁止非法&#xff0c;后果自负 欢迎关注公众号&#xff1…

Windows 10实用优化辅助工具

Windows10优化辅助工具是一款专为Win10系统打造的优化工具&#xff0c;内置多种功能可以大大方便用户使用电脑&#xff0c;一键处理快速高效&#xff0c;让大家用不着差注册表&#xff0c;设备管理器等等繁琐操作&#xff0c;一键优化快速高效&#xff0c;有需要的朋友欢迎使用…

常用的开发辅助软件

记录一些常用的开发辅助软件&#xff08;本文随时更新…&#xff09; 国外的一个绿色、无广告、无捆绑的软件下载站&#xff1a;Softonic  后文中的许多软件可在Softonic上下载。 截取Gif图片&#xff1a; ScreenToGif&#xff08;除截取Gif动图之外&#xff0c;内置Gif编辑器…

软件工程文档编写辅助工具

如下是在编写软件工程相关文档中常用到的辅助工具&#xff0c;欢迎补充 流程图 visio 或者 edrawUML图 StarUML数据库设计 PowerDesigner时序图 visio项目计划 project2016产品原型 Axure