首页 > 编程语言 >【并发编程神器】,Worker Thread模式

【并发编程神器】,Worker Thread模式

时间:2023-07-13 23:31:50浏览次数:27  
标签:调用 Thread Worker 编程 Request 线程 执行 Channel

何为WT模式,如何实现?

类比程序员的日常:办公室里执行 OKR 的程序员们,如果产品需求池有任务了,大家一起分任务,需求池空了(有生之年基本不会空)就摸鱼。

  • WT 中的 Worker Thread就是我们这些干活的程序员。
  • 【并发编程神器】,Worker Thread模式_方法调用

代码实现容易想到用阻塞队列做需求池,然后指定创建若干个线程消费阻塞队列中的任务。这就是线程池。

模式角色

  • Client (委托者)
  • Client创建表示工作请求的Request并将其传递给Channel。示例中由ClientThread扮演
  • 【并发编程神器】,Worker Thread模式_阻塞队列_02

  • Channel(通信线路)
  • Channel接收来自于Client的Request,并将其传递给Worke。示例程序中,由Channel扮演
  • 【并发编程神器】,Worker Thread模式_调用方法_03

  • Worker(工人)
  • Worker从Channel获取Request,并进行工作。当一项工作完成后,它会继续去获取另外的Request。示例中,由WorkerThread类扮演。
  • 【并发编程神器】,Worker Thread模式_方法调用_04

  • Request (请求)
  • 表示工作。Request 保存了进行工作所必需的信息。
  • 【并发编程神器】,Worker Thread模式_方法调用_05

【并发编程神器】,Worker Thread模式_调用方法_06

【并发编程神器】,Worker Thread模式_阻塞队列_07

【并发编程神器】,Worker Thread模式_方法调用_08

该模式有什么好处呢?

提高吞吐量

将工作交给其他线程,自己就可以做别的工作。这是Thread-Per-Message模式的思想。 但由于启动新线程需要花费时间,所以WT模式的思想之一就是通过轮流、反复使用线程来提高吞吐量。

容量控制

可以同时提供的服务的数量,即容量控制:

Worker数量

Worker数量可自定义。示例中,传递给 Channel的构造函数的参数threads即表示这个数值。Worker会创建threads个 WorkerThread 实例。 Worker角色的数量越多,可以并发进行的处理也越多。但是,即使Worker角色的数量超过了 同时被请求的工作的数量,也不会对提高程序处理效率有什么帮助。因为多余的Worker角色不但不会工作,还会占用内存。增加容量就会增加消耗的资源,所以必须根据程序实际运行的环境调整Worker数量。

Worker数量不一定必须在程序启动时确定,也可以像下面这样动态地改变Worker角色 的数量。

  • 最开始只有几个Worker
  • 当工作增加时就增加Worker
  • 但若增加得太多会导致内存耗尽,因此到达极限值后就不再增加Worker
  • 反之,当工作减少(即等待工作的Worker角色增加)时,就要逐渐减少Worker角色

这些 JDK 线程池都实现好了。

Request 数量

Channel保存着Request。只要Worker不断工作,在Channel中保存的Request就不会增加很多。不过,当接收到的工作数量超出 Worker处理能力, Channel中就会积累很多Request。 这时,Client必须等待一段时间才能将Request发给Channel。示例的线程会在Channel类的putRequest方法中wait。 如果Channel角色可以保存很多Request角色,那么就可以填补(缓冲)Client角色与Worker 角色之间的处理速度差异。但是,保存Request角色会消耗大量的内存。因此,这里我们需要权衡 容量与资源。

调用与执行分离

对比Worker Thread模式中的【工作请求】与【普通的方法调用】 Client负责发送工作请求。它会将工作内容封装为Request,然后传给Channel。在普通的方法调用中,这部分相当于“设置参数并调用方法”:

  • 【设置参数】与【创建 Request】对应
  • 【传递给Channel】与【调用方法】对应

Worker负责工作。它使用从Channel接收到的Request执行实际处理。 在普通的方法调用中,这相当于【执行方法】。 在进行【普通的方法调用】时,“调用方法”和“执行方法”是连续进行的。因为调用方法后,方法会立即执行。在【普通的方法调用】中,调用与执行无法分离。

但在Worker Thread、Thread-Per-Message模式,方法的调用和方法的执行被有意分离。方法的调用被称为invocation (动词为invoke ),方法的执行则被称为execution (动词为 execute )。调用与执行的分离同时也是Command命令设计模式。

方法的invoke (调用)与execute (执行)是成对的。ExecutorService 接口的submit (提交)与 execute (执行)也是成对的。

调用和执行分离究竟有什么意义呢?

提高响应速度

如果调用和执行不可分离,那么当执行需要花费很长时间时,就会拖调用处理的后腿。但是如果将调用和执行分离,那么即使执行需要花费很长时间也没有什么关系,因为执行完调用处理的一方可以先继续执行其他处理,这样就可以提高响应速度。

控制执行顺序(调度)

如果调用和执行不可分离,那么在调用后就必须开始执行。 但是如果将调用和执行分离,执行就可以不再受调用顺序的制约。我们可以通过设置Request 优先级,并控制Channel将Request传递给Worker的顺序来实现上述处理。这 种处理称为请求调度(scheduling )。

可以取消和反复执行

将调用和执行分离后,还可以实现“即使调用了也可以取消执行”这种功能。 由于调用的结果是Request对象,所以既可以将Request保存,又可以反复地执行。

通往分布式

将调用和执行分离后,可以将负责调用的计算机与负责执行的计算机分离开来,然后通过网络将扮演Request对象从一台计算机传递至另外一台计算机。

Runnable接口的意义

Runnable接口有时会被用作Worker Thread模式中的Request。即该模式会创建一个实现 Runnable接口的类的实例(Runnable对象)表示工作内容,然后将它传递给Channel,让其完成这项工作。

Runnable对象可以作为方法参数传递,可以被放入到队列中,可以跨越网络传递,也可以被保存至文件中。然后,这样的Runnable对象不论被传递到哪台计算机中的哪个线程中,都可以运行。 这时,我们可以将Runnable接口看作GoF的Command模式中的Command角色。

标签:调用,Thread,Worker,编程,Request,线程,执行,Channel
From: https://blog.51cto.com/JavaEdge/6717176

相关文章

  • 2023-07-13:如果你熟悉 Shell 编程,那么一定了解过花括号展开,它可以用来生成任意字符串
    2023-07-13:如果你熟悉Shell编程,那么一定了解过花括号展开,它可以用来生成任意字符串。花括号展开的表达式可以看作一个由花括号、逗号和小写英文字母组成的字符串定义下面几条语法规则:如果只给出单一的元素x,那么表达式表示的字符串就只有"x"。R(x)={x}例如,表达式"a"......
  • Python 并发编程之协程(转载)
    Python并发编程之协程https://www.cnblogs.com/linhaifeng/articles/7429894.html引子本节的主题是基于单线程来实现并发,即只用一个主线程(很明显可利用的cpu只有一个)情况下实现并发,为此我们需要先回顾下并发的本质:切换+保存状态cpu正在运行一个任务,会在两种情况下切走去执......
  • STM32:rtthread_消息队列
    1消息队列  消息队列是一种常用的线程间异步通讯方式;   消息队列能够接收来自线程或中断中不固定长度的消息,并把消息缓存在自己的内存空间中,供线程间进行异步通讯;  1.1结构体定义//rtconfig.h源码默认注释掉未开启,用到消息队列的时候需要自己开启;#defineRT_USI......
  • 1 Linux系统编程入门
    1Linux系统编程入门1.1Linux开发环境搭建我使用的是阿里云2核2G的服务器1年108元设置服务器root密码,重启服务器root用户登录,进行添加新用户注册自己使用的用户sudouseradd-r-m-s/bin/bashtset#tset是用户名其中参数的意义如下:-r:建立系统账号-m:自动建立用户的......
  • 暑假到了,你家小孩有学编程吗?
    暑假到了,孩子下学期要上一年级,住的地方比较偏,没有编程培训班,买了一块BBC的microbit开发板,带孩子一起学编程。视频内容持续更新中,欢迎大家一起学习交流,陪伴孩子共同成长。欢迎点赞关注转发,一键三连哦~  https://www.bilibili.com/video/BV1EN411U7Fx/https://www.bilibili.......
  • Bootstrap 4 教程_编程入门自学教程_菜鸟教程-免费教程分享
    教程简介Bootstrap4是功能强大且流行的移动第一前端框架,用于在Web上构建响应式移动第一站点。这是Bootstrap的最新版本,它使用HTML,CSS和JavaScript。为什么要使用Bootstrap?它包含整个库中的移动优先样式,而不是在单独的文件中使用它们。只需具备HTML和CSS的知识,任何人都可以开......
  • 【雕爷学编程】Arduino动手做(160)---HLK-V20离线语音模块2
    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手试试多做实验,不管成功与否,都会记录下来——小小的进步或是搞不掂的问题......
  • 2023烟台7天编程集训笔记4
    匈牙利算法点击查看代码//匈牙利算法代码//匈牙利算法可用邻接矩阵和编表,优化用编表,不优化用邻接矩阵//时间复杂度:O(n^3)#include<bits/stdc++.h>usingnamespacestd;boolz[maxn][maxn],vis[maxn];//z[i][j]代表左边第i个点和右边第j个点能不能匹配vis[i]代表右边......
  • 【雕爷学编程】Arduino动手做(138)---64位WS2812点阵屏模块8
    37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞......
  • 编程常识
    BSD函数BSD(BerkeleySoftwareDistribution)是一个基于Unix的操作系统,它包含了一系列的系统调用和库函数。以下是一些常见的BSD函数:socket函数:用于创建一个套接字,用于网络通信。bind函数:将一个套接字绑定到一个特定的IP地址和端口号。listen函数:将一个套接字设置为监听状态,等......