多线程处理的结果顺序完成和结束

多线程处理任务并合并数据 一、线程池创建四种方式 Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。 newScheduledThreadPool 创建一个定时线程池,支持定时及... 阅读详情

多线程处理的结果顺序完成和结束

注意:本文章讲的是多线程如何顺序结束,不是多线程如何顺序执行!

使用场景:

主线程每次收到一批数据处理后,需要对数据进行处理,数据长度和大小不定,有的几毫秒就处理好了,有的几秒钟才能处理完。如果采用单线程,耗时过长肯定是无法接受的,所以选择使用多线程。

但是!每一批数据处理完成后,还需要按照接收到数据的顺序,将处理的数据发送出去,所以每一个数据发送完成前还要判断前一个数据是否发送完成。

真的是···很让人头痛。

比如:我们有一个List,现在需要for循环处理这个List,每一个String对象我们都开启一个线程去处理它,最后我们需要将处理的结果按for循环的顺序发送到其他地方。

解决方案:

一、常用方案

等待所有线程全部结束后,按顺序发送。

理论上来说:这不算是多线程的顺序结束,算是最终结果的顺序执行。即我们使用CountDownLatch或者CompletableFuture来阻塞线程,等待所有的线程或者异步任务处理完成后,将结果进行for循环处理。

需要注意的是:使用这种方式获取到的结果List顺序不一定是按照for循环的顺序,需要加标识进行排序处理。

这种方法实现比较简单,但是处理时间取决于当前批次数据的最长数据处理时间。比如当前批次数据某个线程处理长达10秒,那么所有线程处理完的时间就是10秒+for循环发送时间,比for循环单线程处理快是肯定。

二、嵌套方案(效率优于常用方案)

因为处理数据部分是不要求顺序的,只有在发送时才要求顺序发送。那么我想是不是有一种方案,可以先让所有线程进行数据处理,然后当数据处理部分完成后,卡在发送部分前面。因为是for循环执行的线程,所以每一个线程都可以设置前一个线程作为自己的参数,以此实现嵌套效果,当前线程的前一个线程执行完成后,当前线程才会进行发送处理,以此类推,实现数据处理部分多线程处理,发送部分顺序结束。

代码核心要素:前一个线程作为当前现成的参数、Lock、Condition。

以下是示例代码:

    public void test1(List<String> list) throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(10);
        List<SendTask> sendTaskList = new ArrayList<>();
        Lock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        for (int i = 0; i < list.size(); ++i) {
            String str = list.get(i);
            if (i == 0) {
            //第一个的前一个线程设置为null
                sendTaskList.add(new SendTask(str, null, lock, condition));
            } else {
            //第二次开始,参数为前一个线程
                sendTaskList.add(new SendTask(str, sendTaskList.get(sendTaskList.size() - 1), lock, condition));
            }
        }
		executor.submit(sendTask);
    }

线程处理代码:

public class SendTask implements Runnable {
    private final String message;
    private SendTask previousTask;
    private Lock lock;
    private Condition condition;
    private volatile boolean isDone;


    public SendTask(String message, SendTask previousTask, Lock lock, Condition condition) {
        this.message = message;
        //这里接收上一个线程
        this.previousTask = previousTask;
        this.lock = lock;
        this.condition = condition;
    }


    private void send() {
        // 在这里编写发送逻辑
        System.out.println(message + "开始发送");
        Integer time = 500;
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
//        System.out.println(message + "发送时间" + time);
        System.out.println(message + " 发送完成!");
    }

    @Override
    public void run() {
        try {
//            System.out.printf("%s 开始处理", message);
            Integer time = (new Random().nextInt(3) + 1) * 1000;
            Thread.sleep(time);
//            System.out.println(message + "处理时间" + time);
            lock.lock();
            //如果不是第一个线程,并且前一个线程未执行完成,则等待
            while (previousTask != null && !previousTask.isDone()) {
                condition.await();
            }
            send();
            isDone = true;
            //提醒可以抢锁了
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
        	//解锁
            lock.unlock();
        }
    }

    public boolean isDone() {
        return isDone;
    }

这种方案,就我自己的测试结果来说,是比普通方案要快的,并且顺序是能够得到保障的。但是需要注意的是,Conditon.await()和Lock可能会存在死锁的情况,真实业务代码里需要考虑到这方面,最好设置一个超时时间,避免死锁的发生。

浅谈多线程异步调用获取结果集的几种方式 阅读详情

相关推荐

ESP32S3 Korvo2V3四通道AEC配置实战:基于AFE的回声消除优化

本文详细介绍了在ESP32S3 Korvo2V3平台上配置四通道AEC(回声消除)的实战经验。通过AFE算法优化和硬件连接调试,实现高质量回声消除,显著提升智能音箱和会议设备的语音交互体验。重点解析了四通道配置、数据格式对齐和参数调优等关键技术要点。

elastic6hunter的博客 932

[并发控制]CountDownLatch和CyclicBarrier

在java.util.concurrent 有许多并发工具来帮我们以简单的方式实现多线程的各种机制 今天我们来看CountDownLatch和CyclicBarrier,他们都能实现使线程间等待和唤醒机制。 先来看CountDownLatch,它最主要的方法是countDown(),和await()方法。CountDownLatch允许定义一个数量 表示要等待的线程数。假如有这么一个情景,某个线程需要等待执行某些任务的5个线程执行完毕后在执行。此时可以使用CountDownLatch的构造器传入需要等待的线

lsk_shah的博客 486

[全志T113]:ST7701 86屏幕驱动

[全志T113]:ST7701 86屏幕驱动

LINKKEEE的博客 3141

多线程编程中如何确保子线程执行完毕后主线程再执行-CountDownLatch

定义 ountDownLatch是在java1.5被引入,存在于java.util.cucurrent包下,跟它一起被引入的工具类还有CyclicBarrier、Semaphore、concurrentHashMap和BlockingQueue。 countDownLatch这个类使一个线程等待其他线程各自执行完毕后再执行,它是通过一个计数器来实现的,计数器的初始值是线程的数量。每当一个线程执行完毕后,计数器的值就-1,当计数器的值为0时,表示所有线程都执行完毕,然后在闭锁上等待的线程就可以恢复工作了。 线

梦里蓝天 4049

Star CCM+中的物性参数(定值、多项式、查表)

仿真过程中我们一定会遇到设置物性参数的问题,对于固定的物性参数还好说,直接输入一个固定的值即可。但是对于冷却液、气体、两相流等,物性参数是随着温度或温度和压力变化的。此时就涉及到多项式和查表。首先创建物理连续体,选择计算模型。

2201_75375391的博客 2957

MuJoCo 入门教程(二)

本章介绍 MuJoCo 的数学和算法基础。对于熟悉广义或关节坐标建模和仿真的读者来说,整体框架是相当标准的。因此,我们将对这些材料进行简要总结。本章的大部分篇幅用于介绍我们如何处理接触和其他约束条件。这种方法是基于我们最近的研究,也是 MuJoCo 所独有的,因此我们花时间对其进行了详细的激励和解释。更多信息可参见下面的论文,尽管本章中的一些技术思想是新的,在其他地方还没有描述过。

机器人控制与仿真应用 3712

使用多线程执行任务,并获取返回结果,附异步实现

多线程+异步让程序的效率更高

delete_bug的博客 7647

基于Keil软件实现对射式红外传感器计次 (江协科技HAL库)

用HAL库复现江协科技,让嵌入式学习之路更顺畅。

2401_82728381的博客 798

android等待多个线程结束,给定三个线程如何顺序执行完以后在主线程拿到执行结果...

-欢迎关注我的公众号:![我的公众号](https://markdown-1258186581.cos.ap-shanghai.myqcloud.com/20190606104746.png)# 给定三个线程如何顺序执行完以后在主线程拿到执行结果这里采用线程的 join 方法实现,在一个线程 A 内部如果调用另外一个线程 B 的 join 方法,那么线程 A 就会等待 B 执行完以后再执行。定义线...

weixin_32729025的博客 850

基于Vivado MIG IP核的DDR3读写实验(top_rom_ddr/ddr_top)

一、前言 关于Vivado MIG IP核详细配置可以参考我之前的文章:基于Vivado MIG IP核的DDR3控制器(DDR3_CONTROL) 关于MIG IP核的用户端的接口时序可以参考这篇文章:XILINX 的 MIG IP(非AXI4)接口时序以及控制 二、实验内容 本次实验的内容主要是通过MIG IP核向DDR3读写数据,DDR3的接口时序由ddr_top模块提供: ddr_top模块的数据来源是wr_fifo,wr_fifo的数据实际来自top_sd_photo模块(本实验仿真

耐心的小黑的博客 3027

YOLOv13改进策略【损失函数篇】| 2024 引进Focaler-IoU损失函数 加强边界框回归 (Focaler-DIoU、Focaler-GIoU、Focaler-CIoU)

本文记录的是改进YOLOv13的损失函数,将其替换成。现有研究通过利用边界框之间的几何关系来提高回归性能,但忽略了困难样本和简单样本分布对边界框回归的影响。不同检测任务中困难样本和简单样本的分布不同,对于简单样本占主导的检测任务,关注简单样本的边界框回归有助于提高检测性能;对于困难样本比例较高的检测任务,需要关注困难样本的边界框回归。,提高检测器在不同检测任务中的性能。实现的。

Limiiiing的博客 870

一个多线程并发执行且顺序进出的执行器设计

通过上图我们可以看到,其实这个执行器还是比较简单的,重点就是结果槽是顺序的,执行线程执行完将结果放到对应顺序的结果槽中,而取结果的线程按结果槽的顺序依次从结果槽中取数据,这样就保证了结果是顺序的。需要注意的是结果槽的数量和执行线程的数量是一致的或者大于执行线程数量的,取数据的过程是循环顺序从结果槽中取数据的。考虑这样一种场景,有一批数据需要处理,且每个数据是有顺序的,这时最简单的方式就是按顺序同步执行每个数据的处理。从图中可以看到该执行器分三个部分:数据输入器、并发执行器、结果输出器。

m0_46455711的博客 372

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

多线程计数,等待所有线程执行完后继续执行主线程

多线程计数 public AllDataEntity getAllDdata() throws Exception{ AllDataEntity allDataEntity = new AllDataEntity(); int countThread = 8; CountDownLatch latch = new CountDownLatch(countThread); ExecutorServi...

weixin_39632990的博客 541

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

future.get方法阻塞问题的解决,实现按照任务完成的先后顺序获取任务的结果

1、Future Future模式是多线程设计常用的一种设计模式。Future模式可以理解成:我有一个任务,提交给了Future,Future替我完成这个任务。期间我自己可以去做任何想做的事情。一段时间之后,我就便可以从Future那儿取出结果。 Future提供了三种功能: 判断任务是否完成 能够中断任务 能够获取任务执行的结果 向线程池中提交任务的submit方法不是阻塞方法,而Future...

fourierr的博客 6万+

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

多线程-按顺序放(按顺序取执行结果)

当前有100个有序的任务,要求利用10个线程处理这些任务,并在完成所有任务后保证原有顺序返回;代码如下:import java.util.ArrayList;import...

田维常 1923

python如何在所有线程结束后执行最后操作_如何改变 Python 中线程的执行顺序

一、主线程会等待所有的子线程结束后才结束首先我看下最普通情况下,主线程和子线程的情况。import threadingfrom time import sleep, ctimedef sing():for i in range(3):print("正在唱歌...%d" % i)sleep(1)def dance():for i in range(3):print("正在跳舞...%d" % i)s...

weixin_39653361的博客 3944

ExecutorService等待线程完成后优雅结束

1.概述 该ExecutorService框架可以很容易地在处理多线程任务。我们将举例说明我们等待线程完成执行的一些场景。 此外,我们将展示如何正常关闭ExecutorService并等待已经运行的线程完成其执行。 2.Executor关闭后 使用Executor时,我们可以通过调用shutdown()或shutdownNow()方法将其关闭。虽然,它不会等到所有线程都停止执行。 等待现有线程完成...

淡定_蜗牛的博客 1万+

如何控制多线程执行顺序

static Thread thread1 = new Thread(new Runnable() { @Override public void run() { System.out.println("线程1"); } }); static Thread thread2 = new Thread(n...

liuluteng的博客 3242

python多线程中主线程、子线程谁先结束,主线程结束是否子线程一定结束

最近在学python,对于多线程执行时,主线程是否会主动等着子线程结束后才结束,还是主线程先结束也没关系,子线程会继续执行完毕说法不一,我自己试了,代码如下。 先说结论: 1、主线程可以先于子线程结束,但仅仅是结束(stop状态),主线程对象还在; 2、子线程先于主线程结束,子线程对象直接销毁,表现就是threading.enumerate()里没有那个结束的子线程对象了 所以,用主线程最后一句的打印来判断主线程可以先结束有点草率,要知道打印最后一个符号之前主线程都是好好的 #coding=utf-8 im

weixin_49474047的博客 2050

YOLOv8 + openVINO 多线程数据读写顺序处理

一个典型的生产者-消费者模型,在这个模型中,多个工作线程并行处理从共享队列中获取的数据,并将处理结果以保持原始顺序的方式放入另一个队列。这个例子是ffmpeg读取的数据,用openVINO推理实现对每张图片进行实时推理,推理后的数据,按照顺序写入显示,保证数据顺序一致性。:用于处理好的数据按照读的顺序写入,写入数据到输出队列的顺序是保持一致的。中取出数据进行处理。线程的结束:判断数据里的。多线程处理数据,保证数据先读的先写。:用于存放待处理的数据。:处理完成后,判断数据的。类确保数据的读写正常,

weixin_43763292的博客 1931

多线程按顺序执行

一.前言 本文使用了5中方法实现在多线程中让线程按顺序运行的方法,涉及到多线程中许多常用的方法,不止为了知道如何让线程按顺序运行,更是让读者对多线程的使用有更深刻的了解。 使用的方法如下: [1] 使用线程的join方法 [2] 使用主线程的join方法 [3] 使用线程的线程池方法 [4] 使用线程的CountDownLatch(倒计数)方法 [5]使用线程的Semaphore(信...

技术分享 4536

java 多线程结果_java高效获取多线程执行结果

java高效获取多线程执行结果java创建带有返回值的任务。需要实现Callable接口。实现call()方法。如果不希望有返回结果的可以通过实现Runnable接口覆盖run()方法。那如何多线程下高效的获取任务执行的结果呢。1.下面是常规获取多线程任务返回值结果的方法。import java.util.ArrayList;import java.util.List;import java.ut...

weixin_28789499的博客 619

java 多线程按顺序执行、顺序获取结果

文章目录1、通过Thread的join方法2、FutureTask3、CountDownLatch(倒计数)4、wait、notify5、Condition(条件变量)6、CyclicBarrier(回环栅栏)5、线程池5.1、单线程化线程池5.2、多线程化线程池 1、通过Thread的join方法 join主要是让父线程等待子线程结束之后父线程才能继续运行 public static void main(String[] args) throws InterruptedException {

T-bright的博客 6908

java高效获取多线程执行结果

java高效获取多线程执行结果 java创建带有返回值的任务。需要实现Callable<T>接口。实现call()方法。如果不希望有返回结果的可以通过实现Runnable接口覆盖run()方法。那如何多线程下高效的获取任务执行的结果呢。 1.下面是常规获取多线程任务返回值结果的...

179
上一篇: Vue3下的视频直播流方法(RTSP和HLS流)
下一篇: 企业级中大型监测系统架构设计(基于Prometheus)
黄焖大排骨
博客等级 码龄8年 52粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值