多任务并行处理相关面试题
我自己面试时被问过两次多任务并行相关的问题:
假设现在有10个任务,要求同时处理,并且必须所有任务全部完成才返回结果
这个面试题的难点是:
- 既然要同时处理,那么肯定要用多线程。怎么设计多线程同时处理任务呢?
- 要求返回结果,那么就不能用简单的Thread+Runnable了,这个是无返回结果的
- 最难的是,这些任务彼此间还有关系:任务全部结束才算完成
下面3个Demo,CountDownLatch的结果处理交给大家自行完成。
FutureTask
/*** @author mx*/
public class FutureTaskDemo {private static AtomicInteger count = new AtomicInteger(10);public static void main(String[] args) throws ExecutionException, InterruptedException {// 准备10个线程ExecutorService executorService = Executors.newFixedThreadPool(10);// 收集每个任务的结果List<Future<Integer>> resultList = new ArrayList<>();long start = System.currentTimeMillis();// 并行处理10个任务for (int i = 0; i < 10; i++) {// 准备任务Callable<Integer> task = () -> {// 模拟任务耗时 0~4秒int seconds = ThreadLocalRandom.current().nextInt(5);TimeUnit.SECONDS.sleep(seconds);System.out.println("task is completed! cost:" + seconds + "s left: " + count.decrementAndGet());// 模拟返回结果return 1;};// 提交任务Future<Integer> partResult = executorService.submit(task);// 收集结果resultList.add(partResult);}int result = 0;// 阻塞获取并累加结果for (Future<Integer> future : resultList) {result += future.get();}// 最终全部任务完成,总耗时取决于最耗时的任务时长System.out.println("all task is completed! result=" + result + " cost: " + (System.currentTimeMillis() - start) + "ms");}
}
结果展示
task is completed! cost:0s left: 9
task is completed! cost:1s left: 8
task is completed! cost:1s left: 7
task is completed! cost:2s left: 6
task is completed! cost:3s left: 4
task is completed! cost:3s left: 5
task is completed! cost:3s left: 3
task is completed! cost:3s left: 1
task is completed! cost:3s left: 2
task is completed! cost:4s left: 0
all task is completed! result=10 cost: 4110ms
我原先还写过另一个复杂版本:
/*** @author mx*/
public class FutureTaskDemo {private static AtomicInteger count = new AtomicInteger(10);public static void main(String[] args) throws ExecutionException, InterruptedException {// 准备10个线程ExecutorService executorService = Executors.newFixedThreadPool(10);// 收集任务List<Callable<Integer>> taskList = new ArrayList<>();// 收集结果List<Future<Integer>> resultList = new ArrayList<>();long start = System.currentTimeMillis();// 先准备10个任务for (int i = 0; i < 10; i++) {Callable<Integer> task = () -> {// 模拟任务耗时 0~4秒int seconds = ThreadLocalRandom.current().nextInt(5);TimeUnit.SECONDS.sleep(seconds);System.out.println("task is completed! cost:" + seconds + "s left: " + count.decrementAndGet());// 模拟返回结果return 1;};// 收集任务taskList.add(task);}// 10个任务并行执行for (int i = 0; i < 10; i++) {// 从任务列表取出任务,丢到线程池执行Future<Integer> partResult = executorService.submit(taskList.get(i));// 收集异步结果resultList.add(partResult);}// 最终结果,用于累加int result = 0;// 是否全部结束,否则一直循环等待while (notFinished(resultList)) {// wait for all task to be completed...}// 主线程执行到这,肯定全部任务已经结束,所以get()会立即返回结果,不会再阻塞等待for (Future<Integer> future : resultList) {result += future.get();}// 最终全部任务完成,总耗时取决于最耗时的任务时长System.out.println("all task is completed! result=" + result + " cost: " + (System.currentTimeMillis() - start) + "ms");}/*** 是否全部完成** @param list* @return*/private static boolean notFinished(List<Future<Integer>> list) {for (Future<Integer> future : list) {if (!future.isDone()) {return true;}}return false;}
}
结果展示
task is completed! cost:0s left: 9
task is completed! cost:0s left: 8
task is completed! cost:2s left: 7
task is completed! cost:3s left: 6
task is completed! cost:3s left: 3
task is completed! cost:3s left: 4
task is completed! cost:3s left: 5
task is completed! cost:4s left: 2
task is completed! cost:4s left: 1
task is completed! cost:4s left: 0
all task is completed! result=10 cost: 4051ms
在当前场景下,其实没必要。
有些人可能觉得第一个版本会出现以下问题:
假设总共就2个任务,但是第一个任务耗时3秒,第二个任务耗时1秒。第二个任务的1秒是建立在第一个任务的3秒后,所以总耗时就变成了4秒。
实际上并不会。当future1#get()阻塞获取第一个任务结果的过程中,第二个任务已经完成,所以future2.get()不会再阻塞,而是直接返回结果。
CountDownLatch
CountDownLatch是什么?学名叫闭锁,俗名叫门栓。
/*** @author mx*/
public class CountDownLatchDemo {public static void main(String[] args) throws InterruptedException {// 1.先看简单demo,了解下CountDownLatchmainThreadAndAsyncThread();// 2.尝试使用CountDownLatch解决任务并行问题(不处理结果)
// multiThreadTask();}/*** CountDownLatch简单demo** @throws InterruptedException*/private static void mainThreadAndAsyncThread() throws InterruptedException {// 准备一个countDownLatch,设置10,相当于给门加了10把锁CountDownLatch countDownLatch = new CountDownLatch(10);long start = System.currentTimeMillis();// 副线程去处理任务,每个任务耗时1秒,每处理完1个任务就解开一把锁new Thread(() -> {for (int i = 0; i < 10; i++) {try {Thread.sleep(1000L);} catch (InterruptedException e) {e.printStackTrace();}countDownAndPrint(countDownLatch, 1);}}).start();// 一夫当关,万夫莫开。只要门上10把锁没有全部解开,任何线程都别想想往下走countDownLatch.await();System.out.println("all task is completed! cost: " + (System.currentTimeMillis() - start) + "ms");}/*** CountDownLatch应用:演示10个任务并行执行,全部完成后返回结果** @throws InterruptedException*/private static void multiThreadTask() throws InterruptedException {// 准备一个countDownLatch,设置10,相当于给门加了10把锁CountDownLatch countDownLatch = new CountDownLatch(10);long start = System.currentTimeMillis();// 启动10个线程执行任务for (int i = 0; i < 10; i++) {new Thread(() -> {try {// 线程进来执行任务,随机睡0~4秒int seconds = ThreadLocalRandom.current().nextInt(5);TimeUnit.SECONDS.sleep(seconds);// 每完成一个任务,解开一把锁countDownAndPrint(countDownLatch, seconds);} catch (InterruptedException e) {e.printStackTrace();}}).start();}// 一夫当关,万夫莫开。只要门上10把锁没有全部解开,任何线程都别想想往下走countDownLatch.await();System.out.println("all task is completed! cost: " + (System.currentTimeMillis() - start) + "ms");}/*** countDown()并且打印,其实是不需要加synchronized的,这里只是为了多线程环境下正确打印** @param countDownLatch* @param seconds*/private static synchronized void countDownAndPrint(CountDownLatch countDownLatch, int seconds) {countDownLatch.countDown();System.out.println("task completed, cost: " + seconds + "s left: " + countDownLatch.getCount());}
}
结果展示
task is completed! cost:0s left: 9
task is completed! cost:0s left: 8
task is completed! cost:0s left: 7
task is completed! cost:2s left: 6
task is completed! cost:2s left: 5
task is completed! cost:2s left: 3
task is completed! cost:2s left: 4
task is completed! cost:3s left: 2
task is completed! cost:4s left: 1
task is completed! cost:4s left: 0
all task is completed! result=10 cost: 4049ms
CompletableFuture
顺便说一句,上面的两个Demo都是闹着玩呢,实际开发别傻不拉几地自己写哈...会被打,而且是背身单打颜扣的那种。
/*** @author mx*/
public class CompletableFutureDemo {private static AtomicInteger count = new AtomicInteger(10);public static void main(String[] args) throws InterruptedException, ExecutionException {// 准备10个线程ExecutorService executorService = Executors.newFixedThreadPool(10);// 收集结果List<CompletableFuture<Integer>> resultList = new ArrayList<>();long start = System.currentTimeMillis();// 任务并行for (int i = 0; i < 10; i++) {CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {// 模拟任务耗时 0~4秒try {int seconds = ThreadLocalRandom.current().nextInt(5);TimeUnit.SECONDS.sleep(seconds);System.out.println("task is completed! cost:" + seconds + "s left: " + count.decrementAndGet());} catch (InterruptedException e) {e.printStackTrace();}// 模拟返回结果return 1;}, executorService);resultList.add(completableFuture);}// 处理结果int result = 0;for (CompletableFuture<Integer> completableFuture : resultList) {result += completableFuture.get();}// 最终全部任务完成,总耗时取决于最耗时的任务时长System.out.println("all task is completed! result=" + result + " cost: " + (System.currentTimeMillis() - start) + "ms");}
}
结果展示
task is completed! cost:0s left: 9
task is completed! cost:0s left: 8
task is completed! cost:0s left: 7
task is completed! cost:0s left: 6
task is completed! cost:2s left: 5
task is completed! cost:3s left: 4
task is completed! cost:3s left: 3
task is completed! cost:3s left: 2
task is completed! cost:4s left: 1
task is completed! cost:4s left: 0
all task is completed! result=10 cost: 4051ms
实际开发案例
public class CompletableFutureDemo {private static AtomicInteger count = new AtomicInteger(2);public static void main(String[] args) throws InterruptedException, ExecutionException {// 准备10个线程ExecutorService executorService = Executors.newFixedThreadPool(2);long start = System.currentTimeMillis();// 模拟处理订单CompletableFuture<Void> dealOrder = CompletableFuture.runAsync(() -> {// 模拟任务耗时 0~4秒try {int seconds = ThreadLocalRandom.current().nextInt(5);TimeUnit.SECONDS.sleep(seconds);System.out.println("task is completed! cost:" + seconds + "s left: " + count.decrementAndGet());} catch (InterruptedException e) {e.printStackTrace();}}, executorService);// 模拟处理库存CompletableFuture<Void> dealStock = CompletableFuture.runAsync(() -> {// 模拟任务耗时 0~4秒try {int seconds = ThreadLocalRandom.current().nextInt(5);TimeUnit.SECONDS.sleep(seconds);System.out.println("task is completed! cost:" + seconds + "s left: " + count.decrementAndGet());} catch (InterruptedException e) {e.printStackTrace();}}, executorService);// 可变参数,可以传任意个CompletableFuture,阻塞等待所有任务完成CompletableFuture.allOf(dealOrder, dealStock).get();// 最终全部任务完成,总耗时取决于最耗时的任务时长System.out.println("all task is completed! cost: " + (System.currentTimeMillis() - start) + "ms");}
}
结果展示
task is completed! cost:2s left: 1
task is completed! cost:3s left: 0
all task is completed! cost: 3058ms
相关文章:
多任务并行处理相关面试题
我自己面试时被问过两次多任务并行相关的问题: 假设现在有10个任务,要求同时处理,并且必须所有任务全部完成才返回结果 这个面试题的难点是: 既然要同时处理,那么肯定要用多线程。怎么设计多线程同时处理任务呢&…...
Shell脚本学习笔记
1. 写在前面 工作中,需要用到写一些shell脚本去完成一些简单的重复性工作, 于是就想系统的学习下shell脚本的相关知识, 本篇文章是学习shell脚本整理的学习笔记,内容参考主要来自C语言中文网, 学习过程中,…...
ROS-安装xacro
安装 运行下列命令进行安装,xxxxxx处更改为自己的版本 sudo apt-get install ros-xxxxxx-xacro运行 输入下列命令 roscd xacro如果没有报错,并且进入了xacro软件包的目录,则表示安装成功。 参考: [1]https://wenku.csdn.net/ans…...
为什么说 $mash 是 Solana 上最正统的铭文通证?
早在 2023 年的 11 月,包括 Solana、Avalanche、Polygon、Arbitrum、zkSync 等生态正在承接比特币铭文生态外溢的价值。当然,因铭文赛道过于火爆,当 Avalanche、BNB Chain 以及 Polygon 等链上 Gas 飙升至极值,Arbitrum、zkSync 等…...
安装elasticsearch、kibana、IK分词器、扩展IK词典
安装elasticsearch、kibana、IK分词器、扩展IK词典 后面还会安装kibana,这个会提供可视化界面方面学习。 需要注意的是elasticsearch和kibana版本一定要一样!!! 否则就像这样 elasticsearch 1、创建网络 因为我们还需要部署k…...
Spring中常见的BeanFactory后处理器
常见的BeanFacatory后处理器 先给出没有添加任何BeanFactory后处理器的测试代码 public class TestBeanFactoryPostProcessor {public static void main(String[] args) {GenericApplicationContext context new GenericApplicationContext();context.registerBean("co…...
FPGA LCD1602驱动代码 (已验证)
一.需求解读 1.需求 在液晶屏第一行显示“HELLO FPGA 1234!” 2. 知识背景 1602 液晶也叫 1602 字符型液晶,它是一种专门用来显示字母、数字、符号等的点阵 型液晶模块。它由若干个 5X7 或者 5X11 等点阵字符位组成,每个点阵字符位都可以显示一 个字符,每位之间有一个点距的…...
c++编程要养成的好习惯
1、缩进 你说有缩进看的清楚还是没缩进看的清楚 2、i和i i运行起来和i更快 3、 n%20和n&1 不要再用n%20来判断n是不是偶数了,又慢又土,用n&10,如果n&10就说明n是偶数 同理,n&11说明n是奇数 4、*2和<<…...
后台管理项目的多数据源方案
引言 在互联网开发公司中,往往伴随着业务的快速迭代,程序员可能没有过多的时间去思考技术扩展的相关问题,长久下来导致技术过于单一。为此最近在学习互联网思维,从相对简单的功能开始做总结,比如非常常见的基础数据的…...
视频美颜SDK趋势畅想:未来发展方向与应用场景
当下,视频美颜SDK正不断演进,本文将深入探讨视频美颜SDK的发展趋势,探讨未来可能的方向和广泛的应用场景。 1.深度学习与视频美颜的融合 未来,我们可以期待看到更多基于深度学习算法的视频美颜SDK,为用户提供更高质量…...
C++ const 限定符的全面介绍
C const 限定符的全面介绍 1. const 修饰基本数据类型 定义 const 修饰的基本数据类型变量,值不可改变。 语法 const type variable value;特点 不可变性,增加代码可读性。 作用 定义不可修改的常量。 使用场景 全局常量、配置项。 注意事项…...
Vue 中的 ref 与 reactive:让你的应用更具响应性(上)
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...
华为云CCE-集群内访问-根据ip访问同个pod
华为云CCE-集群内访问-根据ip访问同个pod 问题描述:架构如下:解决方法: 问题描述: 使用service集群内访问时,由于启用了两个pod,导致请求轮询在两个pod之间,无法返回正确的结果。 架构如下&am…...
Kasada p.js (x-kpsdk-cd、x-kpsdk-ct、integrity)
提供x-kpsdk-cd的API服务 详细请私信~ 可试用~ V:zhzhsgg 一、简述 integrity是通过身份验证Kasada检测机器人流量后获得的一个检测结果(数据完整性) x-kpsdk-cd 是经过编码计算等等获得。当你得到正确的解决验证码值之后,解码会看到如下图…...
Thinkphp 5框架学习
TP框架主要是通过URL实现操作 http://servername/index.php/模块/控制器/操作/参数/值.. index.php 为入口文件,在 public 目录内的 index.php 文件; 模块在 application 目录下默认有一个 index 目录,这就是一个模块; 而在 index 目录下有一个 contro…...
麒麟云增加计算节点
一、安装基座系统并配置好各项设置 追加的计算节点服务器,安装好系统,把主机名、网络网线(网线要和其他网线插的位置一样)、hosts这些配置好,在所有节点的/etc/hosts里面添加信息 在控制节点添加/kylincloud/multinod…...
使用Redis进行搜索
文章目录 构建反向索引 构建反向索引 在Begin-End区域编写 tokenize(content) 函数,实现文本标记化的功能,具体参数与要求如下: 方法参数 content 为待标记化的文本; 文本标记的实现:使用正则表达式提取全小写化后的…...
Oracle修改用户密码
文章目录 Oracle修改用户密码Oracle用户锁定常见的两种状态Oracle用户锁定和解锁 Oracle修改用户密码 使用sys或system使用sysdba权限登录,然后执行以下命令修改密码: alter user 用户名 identified by 密码;密码过期导致的锁定,也通过修改…...
LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 描述: 圣诞活动预…...
Vue解决跨域问错误:has been blocked by CORS policy 后端跨域配置
解决跨域问题后端跨域配置代码: /*** 作者 hua* 描述 跨域配置*/ Configuration public class WebConfiguration implements WebMvcConfigurer {/*** 跨域配置对象* return CorsConfiguration对象*/private CorsConfiguration corsConfig() {CorsConfiguration cor…...
【谷歌云】注册谷歌云 创建Compute Engine
文章目录 一、Google Cloud注册1.1 账号信息1.2 付款信息验证1.3 验证成功 二、Compute Engine创建2.1 启动Compute Engine API2.2 创建实例2.3 新建虚拟机实例2.4 等待实例创建完成2.5 查看虚拟机配置信息2.6 创建防火墙规则2.7 SSH远程连接虚拟机 三、参考链接 一、Google Cl…...
面试数据库八股文五问五答第四期
面试数据库八股文五问五答第四期 作者:程序员小白条,个人博客 相信看了本文后,对你的面试是有一定帮助的! ⭐点赞⭐收藏⭐不迷路!⭐ 1)什么情况下 mysql 会索引失效? 不使用索引列进行查询&a…...
2023 年中国金融级分布式数据库市场报告:TiDB 位列领导者梯队,创新能力与增长指数表现突出
近日,沙利文联合头豹研究院发布了中国数据库系列报告之《2023 年中国金融级分布式数据库市场报告》。 报告认为,金融行业对于分布式数据库信任度与认可度正在逐步提高,中国金融级分布式数据库市场正处于成熟落地的高增长阶段,行业…...
基于ExoPlayer的缓存方案实现
音视频APP 的一个必备功能就是在播放的时候会持续缓存完整个音频,同时进度条会更新缓存进度。但是目前Google推出的播放器ExoPlayer本身并没有提供什么方便的接口去实现这个功能,因此大多数的开发者可能会使用AndroidVideoCache 开源库来实现缓存。 AndroidVideoCache 的原理…...
前缀和算法 -- 寻找数组的中心坐标
个人主页:Lei宝啊 愿所有美好如期而遇 本题链接 力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 输入描述 给定一个数组,接口为int pivotIndex(vector<int>& nums) 输出描述 我们以示例1为例画图解释…...
autograd与逻辑回归
一、autograd—自动求导系统 torch.autograd.backward() torch.autograd.backward()是PyTorch中用于计算梯度的函数。以下是对该函数的参数的解释: 功能:自动求取梯度 • tensors: 用于求导的张量,如 loss • retain_graph : 保存计算图 •…...
Xshell 从github克隆项目:使用ssh方式。
接上文: https://blog.csdn.net/liu834189447/article/details/135247868 是能克隆项目了,但是速度太磕碜了,磕碜到难以直视。 找到另外一种办法,使用SSH克隆项目 速度嘎嘎猛。 首先得能进得去github网站,不能点上边…...
C++:通过erase删除map的键值对
map是经常使用的数据结构,erase可以删除map中的键值对。 可以通过以下几种方式使用erase 1.通过迭代器进行删除 #include <iostream> #include <map> #include <string> using namespace std;void pMap(const string& w, const auto& m) {cout&l…...
华为月薪25K的自动化测试工程师到底要会那些技能!
前言 3年自动化测试软件测试工程师职业生涯中,我所经历过的项目都是以自动化测试为主的。由于自动化测试是一个广泛的领域,我将自己的经验整理了一下分享给大家,话不多说,直接上干货。 自动化测试的目标和实践选择合适的自动化…...
diffusers 源码待理解之处
一、训练DreamBooth时,相关代码的细节小计 ** class_labels timesteps 时,模型的前向传播怎么走?待深入去看 ** 利用class_prompt去生成数据,而不是instance_prompt class DreamBoothDataset(Dataset):"""A dat…...
企业建网站公司多少钱/百度指数app
五、学习LLC谐振变换电路的工作原理 在具有电阻R、电感L和电容C元件的交流电路中,电路两端的电压与其中电流相位一般是不同的。如果调节电路元件(L或C)的参数或电源频率,可以使它们相位相同,整个电路呈现为纯电阻性。…...
手机做网站服务器吗/短视频获客系统
在子线程中new一个Handler为什么会报以下错误? java.lang.RuntimeException: Cant create handler inside thread that has not called Looper.prepare() 这是因为Handler对象与其调用者在同一线程中,如果在Handler中设置了延时操作,则调用…...
网站界面布局/站长工具是什么
据国外媒体报道,Groupon周四提交IPO(首次公开募股)申请,计划最多募集7.5亿美元。Groupon向美国证券交易委员会(SEC)提交监管文件称,该公司计划通过IPO方式上市,股票交易代码为“GRPN”。 Groupon上市了,国内的很多人心…...
北京建设教育协会网站/做了5天游戏推广被抓了
第一次安装JDK1.5,使用Eclipse,毫无问题。后为了改变JDK1.5安装路径故卸载重装,然后就发现用不了; 让我去.metadata/.log查看; !SESSION 2013-10-03 09:39:56.500 ----------------------------------------------- ec…...
wordpress摘要字数的插件/深圳市前十的互联网推广公司
原文地址:http://ec.zdnet.com.cn/managesoft/2009/1104/1503211.shtml 凡是比较或者评测的文章,必然会得到很多的非议,因为每个人的标准都不一样,而且本人也不可能对每个系统都研究透彻。本文整理了18家比较常见的OA产品…...
石家庄网站建设汉狮怎么样/2021年近期舆情热点话题
近日来下载的源代码欲编译,可是总是提示“权限不够”,检查了相应文件的权限,都没有问题。无奈之下,把/bin/sh,/bin/bash等程序的权限都折腾了几遍,却总是不行,返回下面的出错信息:XX…...