并发学习26--多线程 异步模式之工作线程

定义:让有限的工作线程(Worker Thread)来轮流异步处理无限多的任务。线程池便是这种模式。

饥饿

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

若一个线程池有两个线程,能够处理两种任务。但是两种任务间有先后顺序。若来一个任务的时候,线程A先处理,然后需要线程B在线程A内帮助处理后续问题。当来两个任务时,线程A,B同时处理这两个任务,但是没有线程处理后续问题。这时便出现了饥饿现象。

当两个线程处理一个任务时:
import lombok.extern.slf4j.Slf4j;import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;@Slf4j(topic = "TC47")
public class TC47 {static final List<String> foods = Arrays.asList("地三鲜","锅包肉","小炒肉","菠萝饭");static Random random = new Random();static String cooking() { return foods.get(random.nextInt(foods.size()));}public static void main(String[] args) {ExecutorService pool = Executors.newFixedThreadPool(2);//result: 中间有线程2帮助做饭//16:09:36.117 [pool-1-thread-1] DEBUG TC47 - 开始点单了....//16:09:36.148 [pool-1-thread-2] DEBUG TC47 - 开始做饭了....//16:09:36.148 [pool-1-thread-1] DEBUG TC47 - 上菜了: 小炒肉....pool.execute(()->{log.debug("开始点单了....");Future<String> food = pool.submit(() -> {log.debug("开始做饭了....");return cooking();});try {log.debug("上菜了: {}....",food.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}});}
}
当两个线程处理两个任务时--出现饥饿
import lombok.extern.slf4j.Slf4j;import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;@Slf4j(topic = "TC47")
public class TC47 {static final List<String> foods = Arrays.asList("地三鲜","锅包肉","小炒肉","菠萝饭");static Random random = new Random();static String cooking() { return foods.get(random.nextInt(foods.size()));}public static void main(String[] args) {ExecutorService pool = Executors.newFixedThreadPool(2);//result: 线程1,2同时点单,没有线程帮助做饭,出现饥饿//16:13:21.932 [pool-1-thread-2] DEBUG TC47 - 开始点单了....//16:13:21.932 [pool-1-thread-1] DEBUG TC47 - 开始点单了....pool.execute(()->{log.debug("开始点单了....");Future<String> food = pool.submit(() -> {log.debug("开始做饭了....");return cooking();});try {log.debug("上菜了: {}....",food.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}});pool.execute(()->{log.debug("开始点单了....");Future<String> food = pool.submit(() -> {log.debug("开始做饭了....");return cooking();});try {log.debug("上菜了: {}....",food.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}});}
}
避免饥饿

不同类型的任务应使用不同类型的线程池

import lombok.extern.slf4j.Slf4j;import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;@Slf4j(topic = "TC48")
public class TC48 {static final List<String> foods = Arrays.asList("地三鲜","锅包肉","小炒肉","菠萝饭");static Random random = new Random();static String cooking() {return foods.get(random.nextInt(foods.size()));}public static void main(String[] args) {ExecutorService waiterPool = Executors.newFixedThreadPool(1);ExecutorService cookPool = Executors.newFixedThreadPool(1);waiterPool.execute(()->{log.debug("开始点单....");Future<String> food = cookPool.submit(() -> {log.debug("开始做菜....");return cooking();});try {log.debug("上菜了: {}",food.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}});waiterPool.execute(()->{log.debug("开始点单....");Future<String> food = cookPool.submit(() -> {log.debug("开始做菜....");return cooking();});try {log.debug("上菜了: {}",food.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}});}
}

合理创建线程池

  • 线程池过小会导致不能充分利用系统资源,容易产生饥饿现象
  • 线程池过大会导致更多的线程上下文切换,占用更多内存,影响性能
CPU密集型运算

适合做数据分析

线程数=CPU核数+1

I/O密集型运算

当I/O密集运算时,可以利用闲置的CPU。

 任务调度线程池

Timer 

Timer执行定时功能但是task2受task1的Sleep影响。

import lombok.extern.slf4j.Slf4j;import java.util.Timer;
import java.util.TimerTask;
@Slf4j(topic = "TC49")
public class TC49 {public static void main(String[] args) {Timer time = new Timer();TimerTask task1 = new TimerTask() {@Overridepublic void run() {log.debug("Task1...");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}};TimerTask task2 = new TimerTask() {@Overridepublic void run() {log.debug("Task2...");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}};log.debug("start");time.schedule(task1,1000);time.schedule(task2,1000);}
}
 ScheduleExecutorService
schedule()

若任务中发生异常,它不会抛出异常也不会在控制台里打印出来,需要我们自己进行try/catch 捕获或这throw。

import lombok.extern.slf4j.Slf4j;import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;@Slf4j(topic = "TC50")
public class TC50 {public static void main(String[] args) {ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);//延迟1S执行pool.schedule(()->{log.debug("Taks1....");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}log.debug("Finish task1...");},1, TimeUnit.SECONDS);pool.schedule(()->{log.debug("Taks2....");log.debug("Finish task2...");},1, TimeUnit.SECONDS);}
}
SchedulelAtFixedRate() 执行时间会抵消delay时间
//result: 如果有sleep, scheduleAtFixedRate的delay会被第一次执行的时间抵消掉。//task3 第一次执行2S完后,抵消了第二次的delay 1S,所以第二次就直接在2S后执行。
//15:54:14.730 [pool-1-thread-1] DEBUG TC50 - Taks3....
//15:54:16.755 [pool-1-thread-1] DEBUG TC50 - Taks3....
//15:54:18.762 [pool-1-thread-1] DEBUG TC50 - Taks3....
//15:54:20.766 [pool-1-thread-1] DEBUG TC50 - Taks3....//任务,初始延迟时间,延迟周期,时间单位pool.scheduleAtFixedRate(()->{log.debug("Taks3....");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}},1,1,TimeUnit.SECONDS);
scheduleWithFixedDelay() 执行时间不会抵消delay时间
//result: 如果有sleep, scheduleWithFixedDelay的delay不会被第一次执行的时间抵消掉,而是在第二次开始重新计算。
//task4 第一次执行2S完后,再delay 1S,再次执行第二次。//16:04:06.244 [pool-1-thread-1] DEBUG TC50 - Taks4....//16:04:09.280 [pool-1-thread-1] DEBUG TC50 - Taks4....//16:04:12.302 [pool-1-thread-1] DEBUG TC50 - Taks4....//16:04:15.329 [pool-1-thread-1] DEBUG TC50 - Taks4....pool.scheduleWithFixedDelay(()->{log.debug("Taks4....");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}},1,1,TimeUnit.SECONDS);
 异常处理
  • 自己使用try/catch 捕获
  • 使用Callable +Future-->如果有异常就能使用get()拿到异常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/802688.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

css设置主题变量

js设置css变量 document.getElementsByTagName(body)[0].style.setProperty(--theme-color, #5ECB90)js获取css变量 document.getElementsByTagName(body)[0].style.getPropertyValue(--theme-color)css设置css变量 //一般都用:root设置:root {--blue: #1e90ff;--white: #fffff…

比特币挖矿与共识

挖矿是增加比特币货币供应的一个过程。挖矿同时还保护着比特币系统的安全&#xff0c;防止欺诈交易&#xff0c;避免“双重支付”&#xff0c;“双重支付”是指多次花费同一笔比特币。矿工们通过为比特币网络提供算力来换取获得比特币奖励的机会。 矿工们验证每笔新的交易并把…

蓝桥杯每日一题:奶牛选美(DSF)

听说最近两斑点的奶牛最受欢迎&#xff0c;约翰立即购进了一批两斑点牛。 不幸的是&#xff0c;时尚潮流往往变化很快&#xff0c;当前最受欢迎的牛变成了一斑点牛。 约翰希望通过给每头奶牛涂色&#xff0c;使得它们身上的两个斑点能够合为一个斑点&#xff0c;让它们能够更…

用户画像——集群搭建

用户画像——集群搭建 1.设计一个规模合适的集群 1.1.1资源预估 1.1.2 选择服务器 2.部署和管理集群的工具 2.1 Hadoop的发展历程 2.2 部署和管理Hadoop的集群并不简单 三种工具的部署方式 3.自动创建虚拟机 3.1 什么是Vagrant&#xff1f; 3.2 安装Vagrant和概念介绍 3.3 使用…

day 1 将go基础知识复习一下

本文章主要是写自己在做这个项目时候遇到的一些困难&#xff0c;如果都是做这个项目的&#xff08;后端&#xff09;&#xff0c;可以看看 这个是项目网址 gin-vue-admin : https://github.com/flipped-aurora/gin-vue-admin 在此表示对大神奇淼的敬佩 首先&#xff0c;我们…

R-tree

R-tree 是一种空间访问方法的数据结构&#xff0c;用于有效地存储和检索多维空间数据&#xff0c;例如地理坐标、矩形或多边形。它特别适用于处理在空间数据库中常见的空间查询&#xff0c;例如最近邻查询、空间连接和空间范围查询。 R-tree 的设计目的是处理大量空间对象&…

在Windows系统上下载并安装MySQL的详细教程

在这篇教程中&#xff0c;介绍如何在Windows系统上下载并安装MySQL。以下是步骤&#xff1a; 1. 访问MySQL官方网站&#xff1a;https://www.mysql.com/ 2. 在主页上&#xff0c;向下滚动到“Developer Zone”&#xff0c;然后单击“MySQL Community (GPL) Downloads”。 3.…

c++——sort()函数

一、代码和效果 #include<bits/stdc.h> using namespace std;int main() {int a[6]{1,45,2,5,456,7};sort(a,a6);for(int i0; i<6; i){cout<<a[i]<<" "<<endl;}return 0; } 二、sort函数解析 &#xff08;从小到大&#xff09; std::so…

深入理解k8s kube-proxy

1、概述 我觉得只要大家知道kube-proxy是用来配置网络规则的而不是转发流量的&#xff0c;真正的流量由iptables/ipvs来转发就可以了。 网络是k8s的一个关键部分。理解k8s中网络组件如何工作可以帮助更好的设计和配置我们的应用。 kube-proxy就是K8s网络的核心组件。它把我们…

Vue3有哪些常用的API

Vue3提供了许多常用的API&#xff0c;这些API可以帮助开发者更高效地构建和管理Vue应用。以下是一些Vue3中常用的API及其功能描述&#xff1a; ref&#xff1a;ref函数用于创建一个响应式引用。它接受一个初始值&#xff0c;并返回一个响应式的对象&#xff0c;该对象的value属…

C# 系统学习(实例计算器)

下面是一个使用 C# 编写的简易计算器的示例代码。这个计算器将支持加、减、乘、除四种基本运算。 using System;class Calculator {static void Main(string[] args){Console.WriteLine("欢迎使用简易计算器&#xff01;");while (true){Console.WriteLine("请…

从“危”到“机”:HubSpot如何助企业转化出海营销CRM风险?

在全球化的大背景下&#xff0c;越来越多的企业选择出海拓展业务&#xff0c;以寻求更大的发展空间。然而&#xff0c;随着市场的扩大&#xff0c;企业在出海营销过程中也面临着各种风险。为了有效规避这些风险&#xff0c;许多企业选择借助HubSpot这样的专业营销软件。今天运营…

国际数字影像产业园构建成都文创产业园新地标!

国际数字影像产业园区&#xff0c;位于成都市金牛区的核心地带&#xff0c;不仅地理位置得天独厚&#xff0c;而且周边配套设施完善&#xff0c;交通便捷&#xff0c;不止成为北二环的新地标&#xff0c;正在构建成都文创产业园新地标&#xff01; 国际数字影像产业园这一片区…

专利年费缴纳后电子票据

专利年费缴纳后的电子票据 随着信息技术的快速发展&#xff0c;电子票据作为一种新型的支付与记录方式&#xff0c;已经深入到了我们日常生活的各个方面。特别是在知识产权领域&#xff0c;专利年费的缴纳也开始逐步实现电子化。 一、专利年费缴纳的重要性 专利年费是专利权…

Windows本地Clion运行CUDA程序

先要条件 在本地安装Visual Studio并且安装好CUDA。建议先安装VS而不是CUDA。如果先安装CUDA&#xff0c;安装遇到问题可参考&#xff1a;https://blog.csdn.net/Cony_14/article/details/137510909 关键步骤 CLion中创建CUDA项目 左上角-新建-项目-CUDA可执行文件。 针对…

5【PS让图片动起来】系列3-【时间轴 花瓣飘落】

【问题介绍】上章将花瓣拆分为一片片花瓣&#xff0c;现在让这片花瓣【动态】飘落吧~ PS选择“窗口”→ “时间轴” 下方弹出时间轴&#xff0c;其中01:00f就是这个位置为1秒的。中间的0 10f 20f等&#xff0c;为帧速率&#xff0c;也就是一秒的动画时间里有几帧的意思 下图…

Linux进阶篇:磁盘管理(二):LVM的创建、格式化和使用

Linux磁盘管理&#xff08;二&#xff09;&#xff1a;LVM的创建、格式化和使用 一、LVM原理回顾 LVM的工作原理进行一个总结&#xff1a; (1)物理磁盘被格式化为PV&#xff0c;空间被划分为一个个的PE (2)不同的PV加入到同一个VG中&#xff0c;不同PV的PE全部进入到了VG的PE…

2024年【R1快开门式压力容器操作】最新解析及R1快开门式压力容器操作试题及解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【R1快开门式压力容器操作】最新解析及R1快开门式压力容器操作试题及解析&#xff0c;包含R1快开门式压力容器操作最新解析答案和解析及R1快开门式压力容器操作试题及解析练习。安全生产模拟考试一点通结合国家…

比特币革命:刚刚开始

作者&#xff1a;Marius Farashi Tasooji 编译&#xff1a;秦晋 要充分理解比特币及其含义&#xff0c;首先必须理解什么是价值&#xff0c;什么是货币。以及是什么赋予资产价值&#xff1f; 这个问题看似愚蠢&#xff0c;但实际上非常有趣。我们的生活是由我们消费或出售的物品…

scrapy 爬取m3u8视频

scrapy 爬取m3u8视频 【一】效果展示 爬取ts文件样式 合成的MP4文件 【二】分析m3u8文件路径 视频地址&#xff1a;[在线播放我独自升级 第03集 - 高清资源](https://www.physkan.com/ph/175552-8-3.html) 【1】找到m3u8文件 这里任务目标很明确 就是找m3u8文件 打开浏览器…