工作窃取(Work-Stealing)是什么?

工作窃取(Work-Stealing)是什么?

工作窃取是一种并行任务调度算法,用于最大化 CPU 资源利用率,特别适合任务分解递归式的并发场景。其核心思想是:当某个线程完成了自己分配的任务后,如果其他线程仍然有未完成的任务,该线程会从其他线程的任务队列中“窃取”任务执行,避免线程处于空闲状态。

底层原理

工作窃取的关键机制依赖于双端队列(Deque)。每个线程都有一个任务队列,遵循以下原则:

  1. 任务分解与执行

    • 每个线程以栈模式(LIFO)从队列的尾部取任务执行。任务可以递归分解成更小的子任务。
    • 当线程空闲时,它从其他线程的任务队列的头部窃取任务,以队列模式(FIFO)执行被窃取的任务。
  2. 双端队列的使用

    • 尾部(栈顶)执行:线程优先执行自己分解的任务,保证局部性。
    • 头部(队列头)窃取:当线程空闲时,其他线程可以从双端队列的头部取任务,避免争用资源。
  3. 高效并行性:由于每个线程主要处理自己的任务队列,只有在窃取任务时才会涉及竞争,因此减少了线程间的锁竞争,提高了并发效率。

工作窃取的运行结果

  • 任务均衡性:工作窃取确保所有线程都能忙碌工作,最大限度利用系统资源。
  • 负载动态分配:由于任务是动态地被其他线程窃取,系统能够根据负载情况自适应调整任务分布。
  • 高吞吐量:工作窃取的机制避免了因为某些线程空闲而导致的资源浪费,提升了整体系统吞吐量。

实现工作窃取的代码示例

import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;

class WorkStealingTask extends RecursiveTask<Integer> {
    private int start;
    private int end;
    private static final int THRESHOLD = 10; // 任务分解的阈值

    public WorkStealingTask(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        // 如果任务规模小于阈值,直接计算
        if ((end - start) <= THRESHOLD) {
            int sum = 0;
            for (int i = start; i <= end; i++) {
                sum += i;
            }
            System.out.println(Thread.currentThread().getName() + " calculated sum: " + sum);
            return sum;
        } else {
            // 分裂任务
            int middle = (start + end) / 2;
            WorkStealingTask leftTask = new WorkStealingTask(start, middle);
            WorkStealingTask rightTask = new WorkStealingTask(middle + 1, end);

            // 异步执行子任务
            leftTask.fork();
            int rightResult = rightTask.compute();
            int leftResult = leftTask.join(); // 等待leftTask完成

            return leftResult + rightResult; // 返回结果
        }
    }
}

public class WorkStealingExample {
    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool(); // 创建ForkJoinPool
        WorkStealingTask task = new WorkStealingTask(1, 100); // 创建任务
        int result = pool.invoke(task); // 提交任务并获取结果

        System.out.println("Final Result: " + result);
    }
}

运行结果

ForkJoinPool.commonPool-worker-1 calculated sum: 55
ForkJoinPool.commonPool-worker-3 calculated sum: 100
ForkJoinPool.commonPool-worker-5 calculated sum: 55
ForkJoinPool.commonPool-worker-7 calculated sum: 45
Final Result: 5050

代码解释

  1. 任务类 WorkStealingTask

    • 继承了 RecursiveTask<Integer>,适用于需要返回结果的任务。
    • 任务被递归地拆分为更小的子任务,如果任务的大小小于某个阈值(THRESHOLD),则直接进行计算。
    • 对于较大的任务,会将其拆分为左右两个子任务,分别执行,并合并最终的结果。
  2. ForkJoinPool

    • 创建 ForkJoinPool 用于执行分解的任务。每个线程都有自己的任务队列,当线程空闲时,它会尝试从其他线程的队列中窃取任务执行。
  3. 工作窃取机制展示

    • 当任务较大时,某些线程可能会执行较长时间的任务,而其他空闲线程会从队列中窃取任务执行,以加速任务完成。
  4. 输出结果

    • 多个线程同时执行各自的任务,最后汇总计算出的结果。
    • 最终输出的结果是 1 到 100 的总和,即 5050

总结

工作窃取是一种高效的任务调度机制,通过让空闲线程主动去“窃取”其他繁忙线程的任务,能够大幅提升多线程系统中的并发性能。这种机制被广泛应用于 ForkJoinPool 中,实现了递归任务分解和合并,保证了线程的最大化利用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++干货篇】——类和对象的魅力(四)

【C干货篇】——类和对象的魅力&#xff08;四&#xff09; 1.取地址运算符的重载 1.1const 成员函数 将const修饰的成员函数称之为const成员函数&#xff0c;const修饰成员函数放到成员函数参数列表的后面。const实际修饰该成员函数隐含的this指针&#xff08;this指向的对…

IDEA如何查看所有的断点(Breakpoints)并关闭

前言 我们在使用IDEA开发Java应用时&#xff0c;基本上都需要进行打断点的操作&#xff0c;这方便我们排查BUG&#xff0c;也方便我们查看设计的是否正确。 不过有时候&#xff0c;我们不希望进入断点&#xff0c;这时候除了点击断点关闭外&#xff0c;有没有更快速的方便关闭…

深入浅出剖析重量级文生图模型Flux.1

24年8月&#xff0c;Flux.1的发布又一次火爆整个AI绘图领域&#xff0c; 号称AI文生图的“新标杆”&#xff0c;刷新AI图像领域的新格局。 Flux是一款由Black Forest Labs开发的尖端AI图像生成工具&#xff0c;旨在通过先进的技术将文本提示转化为高质量的图像。Flux AI支持多…

利用 OBS 推送 WEBRTC 流到 smart rtmpd

webrtc whip 推流 & whep 拉流简介 RFC 定义 通用的 webrtc 对于 SDP 协议的交换已经有对应的 RFC 草案出炉了。这就是 WHIP( push stream ) & WHEP ( pull stream ) . WHIP RFC Link: https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html WHEP RFC Link:…

总分441数一149专137东南大学820信号数电考研经验电子信息与通信工程电路原920专业基础综合,真题,大纲,参考书。

一. 写在前面的话 本人是23年考生&#xff0c;本科就读于西电电子信息工程&#xff0c;以441分总分&#xff08;数学一149&#xff0c;英语83&#xff0c;专业课820&#xff08;原920信号和数电专业基础综合&#xff09;137&#xff0c;政治73&#xff09;考上东南信院电路与系…

虚拟机(VMwara Workstation17)保姆级别的安装(附软件获取途径)

文章目录 一、虚拟机的作用二、虚拟机的获取三、虚拟机的安装步骤四、总结 一、虚拟机的作用 压根不需要给自己的电脑重装系统&#xff0c;就可以使用Linux系统。简单来说就是虚拟出一个计算机&#xff0c;安装Linux系统&#xff0c;便于学习和工作 关于虚拟机的介绍&#xf…

初识Linux · 预备文件系统

目录 前言&#xff1a; 看看物理磁盘 了解磁盘的存储结构 对磁盘进行逻辑抽象 前言&#xff1a; 我们在上文探讨的问题都是基于文件是被打开的情况&#xff0c;那么对于文件没有被打开的情况&#xff0c;我们是没有探讨过的&#xff0c;而本文作为文件系统的预备知识&…

多ip访问多网站

1.前提配置 关防火墙 关selinux 2.安装web服务程序nginx 3.当前主机添加多地址&#xff08;ip a&#xff09; 4.自定义nginx配置文件通过多地址区分多网站 /etc/nginx/conf.d/test_ip.conf server { #标记为一个虚拟主机} 5.根据配置在主机创建数据文件 6.重启服务加载配…

【ROS2】构建导航工程

1、ROS小车组成 ROS小车由三大件组成:运动底盘、ROS主控、导航传感器。 1.1 运动底盘 运动底盘的硬件由车轮、电机(带编码器)、电机驱动器、STM32控制器、电池等组成。 涉及的知识点主要为:STM32单片机程序、机器人运动学分析 1)STM32单片机程序 单片机程序框架如下:…

Modbus TCP报错:Response length is only 0 bytes

问题描述&#xff1a; 使用modbus_tk库&#xff0c;通过Modbus tcp连接PLC时&#xff0c;python中的一个报错信息&#xff1a; Response length is only 0 bytes报错原因&#xff1a; 与Modbus TCP 服务端建立连接后没有断开&#xff0c;继续作为长连接使用&#xff0c;客户端…

vue3 + ts + element-plus 二次封装 el-dialog

实现效果&#xff1a; 组件代码&#xff1a;注意 style 不能为 scoped <template><el-dialog class"my-dialog" v-model"isVisible" :show-close"false" :close-on-click-modal"false" :modal"false"modal-class&…

Java调用大模型 - Spring AI 初体验

Spring AI&#xff1a;为Java开发者提供高效的大模型应用框架 当前Java调用大模型时面临缺乏高效AI应用框架的问题。Spring作为资深的Java应用框架提供商&#xff0c;通过推出Spring AI来解决这一挑战。它借鉴了LangChain的核心理念&#xff0c;并结合了Java面向对象编程的优势…

提升网络安全防御有效性,服务器DDoS防御软件解读

从购物、银行业务、旅行计划到娱乐&#xff0c;人们越来越多地转向数字领域来促进他们的公共和私人生活。然而&#xff0c;当DDoS攻击汹涌而至&#xff0c;企业很可能会陷入数小时或数天的混乱局面&#xff0c;用户的体验也会大打折扣。根据DDoS-Guard发布的数据&#xff0c;20…

QML 基本动画

在介绍完 QML 动画框架之后,现在我们来看看具体的动画及其用法。先从最常用的基本动画入手,这些动画包括:PropertyAnimation、ColorAnimation、Vector3dAnimation 和 PathAnimation 等,它们不仅能够帮助我们轻松地为应用程序添加动态效果,还能显著提升用户体验,使得界面更…

C++11——智能指针

智能指针的介绍 智能指针是C11中引入的标准库特性之一&#xff0c;智能指针是为了避免手动管理内存时常见的错误&#xff0c;比如内存泄漏、重复释放内存等问题。智能指针通过封装原生指针&#xff08;裸指针&#xff09;和自动释放内存的功能&#xff0c;让开发者更安全和高效…

[渗透]前端源码Chrome浏览器修改并运行

文章目录 简述本项目所使用的代码[Fir](https://so.csdn.net/so/search?qFir&spm1001.2101.3001.7020) Cloud 完整项目 原始页面修改源码本地运行前端源码修改页面布局修改请求接口 本项目请求方式 简述 好久之前&#xff0c;就已经看到&#xff0c;_无论什么样的加密&am…

SPI的学习

工作原理 SPI的工作原理基于主从架构。主设备通过四条主要信号线与一个或多个从设备进行通信&#xff1a; MOSI&#xff08;主输出&#xff0c;从输入&#xff09;DI&#xff08;Master Output Slave Input&#xff09;&#xff1a;主设备发送数据到从设备。MISO&#xff08;…

利用自定义 ref 实现函数防抖

今天来简单介绍一个新的方法&#xff0c;使用自定义 ref 实现函数防抖。 1. 自定义 ref 的来源 自定义 ref 防抖函数来自于前端开发中的两个概念&#xff1a;Vue 的响应式系统 和 数防抖&#xff08;Debounce&#xff09;。 1、Vue 响应式系统&#xff1a;Vue 提供了 ref 和…

SQL 干货 | SQL 反连接

最强大的 SQL 功能之一是 JOIN 操作&#xff0c;它提供了一种优雅而简单的方法&#xff0c;将一个表中的每一条记录与另一个表中的每一条记录结合起来。不过&#xff0c;有时我们可能想从一个表中找到另一个表中没有的值。正如我们将在今天的博客文章中看到的&#xff0c;通过包…

爬虫结合项目实战

由于本人是大数据专业&#xff0c;所以准备的是使用pycharm工具进行爬虫爬取数据&#xff0c;然后实现一个可视化大屏 参考项目&#xff1a; 1.医院大数据可视化最后展示 2. 大数据分析可视化系统展示 代码包&#xff1a;