【并发编程】- 线程池执行任务乱序特性

Java中如何保证线程顺序执行 我是猿人,一个热爱技术、热爱编程的IT猿。技术是开源的,知识是共享的!写作是对自己学习的总结和记录,如果您对 Java、分布式、微服务、中间件、Spring Boot、Spring Clo... 阅读详情

线程池ThreadPoolExecutor执行任务Runnable乱序特性
接口Runnable在线程池ThreadPoolExecutor的队列中是按顺序取出,执行却是乱序的。
线程执行代码如下:

@Slf4j
public class TheRunnable implements Runnable {

    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public TheRunnable(String username){
        super();
        this.username=username;
    }



    @Override
    public void run() {
        try {
            Thread.sleep(2000);
            log.info("线程名:"+username);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行类代码如下:

public class DisorderedOrderRun {
    public static void main(String[] args) {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        for (int i = 0; i < 20; i++) {
            TheRunnable theRunnable = new TheRunnable("G" + (i + 1));
            threadPoolExecutor.execute(theRunnable);
        }
    }
}

运行结果如下:

10:37:06.675 [pool-1-thread-5] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G5
10:37:06.660 [pool-1-thread-3] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G3
10:37:06.675 [pool-1-thread-1] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G1
10:37:06.660 [pool-1-thread-2] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G2
10:37:06.706 [pool-1-thread-4] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G4
10:37:08.692 [pool-1-thread-3] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G6
10:37:08.692 [pool-1-thread-1] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G7
10:37:08.692 [pool-1-thread-5] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G8
10:37:08.692 [pool-1-thread-2] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G9
10:37:08.723 [pool-1-thread-4] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G10
10:37:10.708 [pool-1-thread-3] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G11
10:37:10.708 [pool-1-thread-1] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G12
10:37:10.708 [pool-1-thread-5] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G13
10:37:10.708 [pool-1-thread-2] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G14
10:37:10.739 [pool-1-thread-4] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G15
10:37:12.714 [pool-1-thread-1] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G17
10:37:12.714 [pool-1-thread-3] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G16
10:37:12.714 [pool-1-thread-5] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G18
10:37:12.714 [pool-1-thread-2] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G19
10:37:12.745 [pool-1-thread-4] INFO com.ozx.concurrentprogram.executor.service.TheRunnable - 线程名:G20

从运行结果看出Runnable状态从就绪态到运行态转换,线程各自获取CPU时间片不一样,所以线程执行顺序是乱序的。
通过使用线程池能最大幅度地减少创建线程对象的内存与CPU开销,加快程序运行效率,进而对创建线程类的代码进行了封装。

如何让线程池里面的线程按顺序执行 笔者今天看到一个有趣的面试题,如何让多个线程按照既定的顺序依次执行?比如每个线程输出一个整数,那么期望就是这样的:0,1,2,3,4,5,6,7,8,9.而不是0,2,4,1,3,5,8,7,9,6乍一看,这不是反人性的考题吗?多线程本来就以乱序执行出名的。稍加思索,想到3种解决方案,分别用代码实现之。方法1: 使用join方法方法2:使用newSingleThreadExecutor方法3:使用ThreadPoolExecutor,设置它的核心线程数为1。 阅读详情

相关推荐

多线程执行顺序终极解密:从随机乱序到精准控制的性能飞跃!

多线程的执行顺序问题,Thread类中join方法的运行原理

1515

再谈ThreadPoolExecutor

上次提到分析了ThreadPoolExecutor的核心参数,本文则主要分析下常用队列、拒绝策略和线程池初始化方法。

耘田 927

Java并发编程(2)- FutureTask详解与池化思想的设计和实战一

在Java并发编程领域,FutureTask可以说是一个非常强大的利器,它通过实现RunnableFuture接口间接拥有了Runnable和Future接口的相关特性,既可以用于充当线程执行的任务(Runnable),也可以用于获取线程异步执行任务后返回的结果(Future);本文将基于FutureTask实战一个高级案例:设计一款简化版的池容器,以此学习巩固池化思想.

青松之竹_Java博客 643

(转)ThreadPoolExecutor的执行顺序

[size=medium]ThreadPoolExecutor类关于排队是这样描述的: 所有 BlockingQueue 都可用于传输和保持提交的任务。可以使用此队列与池大小进行交互: [list] [*]如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。 [*]如果运行的线程等于或多于 corePoolSize,则 Executo...

Java红 1046

使用AI编写测试用例——详细教程

现阶段AI还不能完全替代人工测试用例编写,但如果把AI当做一个提高效率的工具,它将会是一个很强大的辅助。

公众号|软件测试老吴 3万+

转录组数据去批次方法整理(combat,combat-seq,removeBatchEffect)

正是因为这些非生物学的因素存在就有可能会导致我们的结果偏离真实的情况,那么实际分析的过程中研究者应当评估是否存在批次效应,并决定是否要进行去批次处理。批次效应是指样本在不同批次处理及测量的情况下引入与生物学情况不相关的技术误差,比如不同试剂耗材,不同操作者,不同的实验时间等。combat函数是基于贝叶斯框架下的调整数据批次效应的函数,主要适用于已经被过滤和标准化后的数据(combat-seq函数是基于二项回归分布下的调整数据批次效应的函数,主要适用于。值得注意的是,即使使用了所谓的去批次效应的工具,

zfyyzhys的博客 7862

线程池

线程池 文章目录线程池0.线程池优点(⭐)1.线程池各种接口框架:2.线程池的执行原理3.如何创建一个线程池4.向线程池中提交任务1.用execute()方法提交,没有返回值2.用submit()方法提交任务,带有返回值5.线程池的关闭(⭐)优雅的关闭线程池(⭐)6.合理配置线程池7. 典型问题1.ThreadPoolExecutor 有哪些常用的方法?3.在 ThreadPool 中 submi...

eternal_yy 381

当LightGBM推理遇上GPU:3种替代方案性能对比(含ONNX实战代码)

本文针对LightGBM官方不支持GPU推理的性能瓶颈,深度评测了RAPIDS cuML、ONNX Runtime GPU和Triton Inference Server三种GPU加速推理替代方案。通过详尽的性能对比和实战代码,为高并发、低延迟的在线预测场景提供了清晰的选型指南,帮助工程师打破推理性能枷锁,实现显著的吞吐量提升。

salt9的博客 813

多线程线程池详解、 线程异步编排和线程串行化

多线程进阶 文章目录多线程进阶前言一、创建多线程的4种方式(回顾)1.1、创建线程1.2、区别1.3 总结二、线程池创建和说明1、自定义线程池1.1、7大参数说明1.2、自定义创建1.3、工作顺序1.4、案例思考2、Executors创建功能性线程池2.1、常见的四种功能性线程池2.2、创建定长线程池2.3、为什么使用线程池三、CompletableFuture异步编排和串行化1.1、CompletableFuture介绍1.2、2种创建方式 前言 多线程,可以先看下小编总结的多线程(一)基础篇==&g

suqinyi的博客 1967

Qt Design Studio 入门指南:从零开始打造炫酷UI(详细+实用+轻松上手)

本文是Qt Design Studio的详细入门指南,旨在帮助UI设计新手从零开始轻松打造炫酷界面。文章系统介绍了软件的核心概念、安装步骤、主界面解析,并通过创建一个完整的登录界面实例,手把手教学如何拖拽组件、设置属性、添加交互状态与动画。同时,分享了创建自定义组件、管理资源以及提升效率的实用技巧与常见问题解决方案,让读者能够快速上手并应用于实际项目开发。

devops8pract的博客 588

告别混乱接线!用EPLAN 3D布局图,手把手教你搞定电气柜的3D建模与自动布线

本文详细介绍了如何使用EPLAN 3D布局图进行电气柜的3D建模与自动布线,帮助工程师告别混乱接线。从项目准备、基础结构建模到智能设备布局与逻辑定义,再到高级布线技术与问题排查,提供了一套完整的实战指南。通过EPLAN的3D功能,显著提升设计效率与系统可靠性。

weixin_30680385的博客 340

ForkJoinPool线程池批量执行任务3

package com.yongyou.test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; ...

lixiaxin200319的博客 522

Jetson Orin Nano GPIO 实战,用 devmem 玩转 Pinmux 引脚复用配置

devmem 是一个直接读写寄存器的工具,通过 mmap 将 /dev/mem 中的物理地址区域映射到用户空间进程地址空间,从而实现直接读写,正常情况下在 /dev 下可以看到 mem。可以看到对应 bit5 bit6 分别为 1,对应配置为 E_IO_HV 为 ENABLE 以及 E_INPUT 为 ENABLE。需要 TRM 手册查看相关寄存器,以及安装 busybox,busybox 内置了 devmem。根据 TRM 手册,找到 I2C_SDA 的 pinmux 地址偏移是 0x18。

darcsdn 1644

python线程池提交任务

2. 方式提交 这种提交方式是一条一条地提交任务: 1. 可以提交不同的任务函数; 2. 线程池的线程在执行任务时出现异常,程序不会停止,而且也看不到对应的报错信息; 3. 得到的结果是乱序的。 3. 方式提交 这种提交方式可以分批次提交任务:

优快云1csdn1的博客 1514

【ComfyUI报错解决】K采样器 mat1和mat2形状不匹配错误分析与修复 mat1 and mat2 shapes cannot be multiplied (77x2048 and 4096x

如果你在 ComfyUI 里遇到K采样器报错:mat1 和 mat2 shapes cannot be multiplied确认大模型和 LoRA 是否是同一版本(SDXL vs SD1.5,不能混用)。如果用了双 CLIP 加载器,要确认加载的类型和选择的模型类型是否匹配。加载→ 类型选flux加载 SDXL 专用的 clip/t5 → 类型选sdxl避免不同版本模型和 LoRA 混搭,保持一致性。模型+LoRA+CLIP 类型必须保持同一版本,不然就会报错。

代码简单说 Vue、JAVA、PHP、Node.js 熟练运用,接口、架构、性能全搞定。 2409

DDR5 JEDEC标准简析:一次读懂DDR5的核心规范!

JEDEC,全称是,中文名称是「电子元件工程联合委员会」,它是全球权威的存储接口标准制定机构。我们常见的 DDR2、DDR3、DDR4、DDR5 都是它搞出来的。📌 JEDEC 就像存储接口界的“裁判+编剧”——规定谁该怎么跑,怎么演,怎么配合。

weixin_43199439的博客 2571

多进程任务结果乱序怎么办,深度剖析imap_unordered工作机制与应对策略

解决多进程任务结果乱序问题,深度剖析多进程池 imap_unordered 的顺序机制与应对策略。适用于高并发数据处理场景,通过结果重排、标识追踪等方法保障输出有序,提升程序可靠性。实用技巧值得收藏。

GatherLume的博客 972

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Java线程池中如何实现任务的优先级执行

优先级队列只是一种排序工具,线程池调度逻辑本身并不感知优先级。真正起作用的是你如何让任务“排队”,以及任务对象本身的可比性是否强。Java 线程池本身不提供“权重轮询”或“时间片保证”机制,只负责从队列中提取任务,而队列只负责排序。在进入队列之前,线程直接执行任务的概率很大。当线程池有空闲线程时,新任务将绕过队列,空闲线程将立即执行。,因此,所有的任务都必须进入队列等待-此时优先级才能真正发挥作用。只要高优任务继续提交,低优任务可能永远不会等到执行。,此时,优先级队列根本没有参与调度。

sillyoung的博客 37

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

复盘 Spring boot 中定时任务如何启用异步线程池

>>号外:关注“Java精选”公众号,回复“2021面试题”关键词,领取全套500多份Java面试题文件。项目中最近使用了多个定时任务处理业务需求,于是在实现业务逻辑过程中,产...

Java精选 521

java并发编程

Java 并发程序都是基于多线程的,自然也会涉及到任务切换,任务切换的 时机大多数是在时间片结束的时候。对于java内存模型来说,为每个线程提供工作内存(缓存),当线程需要操作主内存数据时,需要先将主内存数据加载到自己的工作内存,操作完成后在写回主内存,那么如果两个线程同时执行,在一个线程修改数据后,另一个线程不能及时可见。单核cpu下,线程其实是串行执行的。操作系统中有一个组件叫做任务调度器,将cpu的时间片,分给不同的线程使用,只是由于cpu在线程间(时间片很短)的切换非常快,人类感觉是同时运行·的。

2302_81981929的博客 538

并发编程_

java内存模型的缓存区导致了不可见性,编译器优化导致了乱序性,线程的切换执行导致了指令的非原子性。

2301_78085386的博客 1050

并发编程

若已有元素,第一个元素作为锁对象,使用sync加锁,这样会降低锁的粒度,可以同时有多个方法进入到put中操作,提高并发效率。为每个线程创建一个ThreadLocalMap对象,用来保存磁县城拥有的变量,在每个线程中的ThreadLoacl中,用当前操作的ThreadLoacl对象作为键。当一个线程进入到一个同步方法中,然后再次方法中要调用另一个同步方法,而且两个方法共用一把锁,此时线程是可以进入到另一个同步方法中的。每次为线程赋值时,首先获取当前线程对象,拿到当前线程对象中的ThreadLocalMap。

2301_77112787的博客 858

并发编程:线程池、volatile、synchronized

仅状态标记、无并发修改 → volatile共享变量多线程读写、计数同步 → synchronizedIO 密集批量任务控制并发 → 自定义 ThreadPoolExecutor高并发计数场景 → LongAdder(性能优于 synchronized 同步变量)

weixin_43590392的博客 359

Spark源码中的线程池

线程池类型Spark 应用场景设计哲学关键配置参数​​核心调度、网络通信​​稳定压倒一切​​​​事件总线、资源清理​​顺序性保证正确性​​​​结果处理、临时任务​​弹性应对突发流量​​​​资源分配、心跳检测​​时间驱动型任务​​。

weixin_44426359的博客 1173
上一篇: 使用无界队列的线程池会导致内存飙升吗?
下一篇: ZooKeeper系列:session会话
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值