half-sync/half-async 和 Leader/Followers 模式的主要区别

在 《POSA2》 一书中,关于这两个模式有两个很形象的比喻:

半同步/半异步(half-sync/half-async):
许多餐厅使用 半同步/半异步 模式的变体。例如,餐厅常常雇佣一个领班负责迎接顾客,并在餐厅繁忙时留意给顾客安排桌位,为等待就餐的顾客按序排队是必要的。领班由所有顾客“共享”,不能被任何特定顾客占用太多时间。当顾客在一张桌子入坐后,有一个侍应生专门为这张桌子服务。

领导者/追随者(Leader/Followers):
在日常生活中,领导者/追随者模式用于管理许多飞机场出租车候车台。在该用例中,出租车扮演“线程”角色,排在第一辆的出租车成为 领导者,剩下的出租车成为 追随者。同样,到达出租车候车台的乘客构成了必须被多路分解给出租车的事件,一般以先进先出排序。一般来说,如果任何出租车可以为任何顾客服务,该场景就主要相当于 非绑定句柄/线程关联。然而,如果仅仅是某些出租车可以为某些乘客服务,该场景就相当于 绑定句柄/线程关联。

在 《POSA2》 书中列举的例子都比较复杂,并且书上没有列出完整的代码。但是这两个模式其实都可以在 《unix网络编程》一书中找到对应的完整的代码和相关的讨论。

在 半同步/半异步 模式中,需要由模式实现者显示构造一个队列,以便同步层和异步层可以通信。
在 《unix网络编程》 一书的 “27.12 TCP预先创建线程服务器程序,主线程统一 accept” 的例子中, 如果只是从处理 accept 这个事件上看,可以认为这是一个使用了 半同步/半异步 模式的例子。但是从具体的业务处理(即web_child的处理上),仍然可以认为是一个ThreadPerConnection模型,因为在 thread_main 中直接读取请求和发送响应。在这个例子中,就有一个队列:

Java代码  收藏代码
  1. [b]//这就是一个典型的循环队列的定义,iget 是队列头,iput 是队列尾[/b]  
  2. int clifd[MAXNCLI], iget, iput;   
  3.   
  4. int main( int argc, char * argv[] )  
  5. {  
  6.   ......  
  7.   int listenfd = Tcp_listen( NULL, argv[ 1 ], &addrlen );  
  8.   ......  
  9.   
  10.   iget = iput = 0;  
  11.   
  12.   forint i = 0; i < nthreads; i++ ) {  
  13.     pthread_create( &tptr[i].thread_tid, NULL, &thread_main, (void*)i );  
  14.   
  15.   for( ; ; ) {  
  16.     connfd = accept( listenfd, cliaddr,, &clilen );  
  17.     clifd[ iput ] = connfd;     [b]// 接受到的连接句柄放入队列[/b]  
  18.     if( ++iput == MAXNCLI ) iput = 0;    
  19.   }  
  20. }  
  21.   
  22. void * thread_main( void * arg )  
  23. {  
  24.   for( ; ; ) {  
  25.     while( iget == iput ) pthread_cond_wait( ...... );  
  26.     connfd = clifd[ iget ];     [b]// 从队列中获得连接句柄[/b]  
  27.     if( ++iget == MAXNCLI ) iget = 0;  
  28.     ......  
  29.     web_child( connfd );  
  30.     close( connfd );  
  31.   }  
  32. }  



而在 领导者/追随者 模式中,同样是有一个队列的,不过不需要模式实现者显示构造,而是直接使用了操作系统底层的队列。

在 《unix网络编程》 一书的 “27.11 TCP 预先创建服务器线程,每个线程各自 accept ” 的例子中,就是直接使用了操作系统中关于 accept 的队列。这个例子可以认为是 领导者/追随者 模式的一个例子。

Java代码  收藏代码
  1. int listenfd;  
  2.   
  3. int main( int argc, char * argv[] )  
  4. {  
  5.   ......  
  6.   listenfd = Tcp_listen( NULL, argv[ 1 ], &addrlen );  
  7.   ......  
  8.   forint i = 0; i < nthreads; i++ ){  
  9.     pthread_create( &tptr[i].thread_tid, NULL, &thread_main, (void*)i );  
  10.   }  
  11.   ......  
  12. }  
  13.   
  14. void * thread_main( void * arg )  
  15. {  
  16.   for( ; ; ){  
  17.     ......  
  18.     [b]// 多个线程同时阻塞在这个 accept 调用上,依靠操作系统的队列[/b]  
  19.     connfd = accept( listenfd, cliaddr, &clilen );  
  20.     ......  
  21.     web_child( connfd );  
  22.     close( connfd );  
  23.     ......  
  24.   }  
  25. }  


当然,这里提到的操作系统的队列,在 半同步/半异步 模式中虽然没有明显地指出来,但只要是通过操作系统来做 accept ,那么在 半同步/半异步 模式中仍然会隐式地用到。

在 《POSA2》中,作者的评价:
因为半同步/半异步设计在 web 服务器虚拟内存而不是操作系统内核内排队请求,所以它更具伸缩性。


看了上面的代码之后,明白了为何 ACE 的作者在 《C++网络编程2》 中特意引用了一首诗来“表达我们对 Richard 之持久影响的看法”:

不是在悲哀的冥河之滨,也不是在遥远的
乐土般的平原的清辉中,我们将在死者中间
遇见那些我们一直是其学生的人 ... ...
我们还将相遇,分离,再相遇,
在死者们相遇的地方,在活着的人的唇上


关于不同的客户-服务器编程模型,在 《unix网络编程》的 “第27章 客户-服务器程序的其他设计方法”中讨论得很充分,对每种模型的性能也做了很好的分析。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JAVA中的IO系统详解

Java 流在处理上分为字符流和字节流。字符流处理的单元为 2 个字节的 Unicode 字符&#xff0c;分别操作字符、字符数组或字符串&#xff0c;而字节流处理单元为 1 个字节&#xff0c;操作字节和字节数组。 Java 内用 Unicode 编码存储字符&#xff0c;字符流处理类负责将外部…

将Linux下编译的warning警告信息输出到文件中

Linux中&#xff0c;脚本语言环境中&#xff0c;即你用make xxx即其他一些普通 linux 命令&#xff0c;比如ls&#xff0c;find等&#xff0c;不同的数字&#xff0c;代表不同的含义&#xff1a; 数字 含义标准叫法0标准输入stdin standard input1标准输出stdout standard o…

java 内部编码_Java 中文编码分析

一、charAt 与 codePonitAt我们知道 Java 内部使用的是 utf-16 作为它的 char、String 的字符编码方式&#xff0c;这里我们叫它内部字符集。而 utf-16 是变长编码&#xff0c;一个字符的编码被称为一个 code point&#xff0c;它可能是 16 位 —— 一个 code unit&#xff0c;…

Framework1.1 DataView 转DataTable

因为Framework2.0开始DataView 有toTable()方法&#xff0c;可以直接转。但vs2003还是Framework1.1 没有这个方法。 所以要手动转&#xff0c;方法如下&#xff1a; public static DataTable CreateTable(DataView obDataView) { if (null obDataView) …

leetcode mysql 排名_(LeetCode:数据库)分数排名

编写一个 SQL 查询来实现分数排名。如果两个分数相同&#xff0c;则两个分数排名(Rank)相同。请注意&#xff0c;平分后的下一个名次应该是下一个连续的整数值。换句话说&#xff0c;名次之间不应该有“间隔”。-----------| Id | Score |-----------| 1 | 3.50 || 2 | 3.65…

Windows 8 JavaScript Metro应用程序--入门(上)

Windows 8 JavaScript Metro应用程序--入门&#xff08;上&#xff09; 如你所知的Windows8允许你通过以下几种方式创建Metro应用程序&#xff1a; CC# JavaScript第一部分将侧重于主体结构和JavaScript Grid 应用程序的基础&#xff0c;在随后的文章中我将深度探究在Windows8中…

内核编译(make)

内核编译&#xff08;make&#xff09;之后会生成两个文件&#xff0c;一个Image&#xff0c;一个zImage&#xff0c;其中Image为内核映像文件&#xff0c;而zImage为内核的一种映像压缩文件&#xff0c;Image大约为4M&#xff0c;而zImage不到2M。 那么uImage又是什么的&#…

cobol to java_cobol to java

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼(a) Javaソースプログラムの作成COBOLプログラムを呼び出すJavaプログラムでは&#xff0c;次の三つのJavaソースファイルを作成する必要があります。mainメソッドを含むJavaプログラム(Javaクラス)COBOLプログラムに対応するJava…

Elf

机器执行的是机器指令&#xff0c;而机器指令就是一堆二进制的数字。高级语言编写的程序之所以可以在不同的机器上移植就因为有为不同机器设计的编译器的存在。高级语言的编译器就是把高级语言写的程序转换成某个机器能直接执行的二进制代码。以上的知识在我们学习CS(Computer …

python教程闭包_Python教程 闭包的特性

作者&#xff1a;Vamei 出处&#xff1a;http://www.cnblogs.com/vamei 欢迎转载&#xff0c;也请保留这段声明。谢谢&#xff01;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~闭包(closure)是函数式编程的重要的语法结构。函数式编…

直接打印报表

在ax中有时可能需要在打印时&#xff0c;不显示报表的预览与设置窗口&#xff0c;而是直接Send到打印机。可以使用ClassFactory、PrintJobSettings、ReportRun来完成。 static void NJ_MF_DirectPrint(Args _args) { Args args new Args(); ReportRun …

如何构建自己的SIP SERVER!

如果你下载了 sip phone, 自己又做了一个 SIP SERVER,那么你就可以当老大了&#xff0c;不要什么MSN&#xff0c;QQ的语音通话了&#xff0c;自己就可以直接同你想要的人通话了。1&#xff1a;软件准备&#xff1a;A: SIP SERVER http://www.brekeke.com/en/download/idx_sipse…

java java.lang_Java之java.lang.IllegalMonitorStateException

今天又中彩了, 原本很简单的多线程程序, 蓦然间冒了个"java.lang.IllegalMonitorStateException" , 杀了个措手不及. 一直纳闷, 为什么为什么? 查资料说该异常由于对象未获取得到Lock就试图操作Lock. 再细细源码, 原来不不小将lock.lock()写错为lock.tryLock(). 坑爹…

CruiseControl.NET ----- mail 配置

最近在用 CruiseControl.NET实现每日构建&#xff0c;其他配置起来都挺方便&#xff0c;就是在邮件设置上费了不少时间,我用的是CC.NET1.6,这个版本已经支持发送附件&#xff0c;如果使用外部邮箱&#xff0c;记得要把邮箱的smtp功能打开&#xff0c;下面是Mail配置的一个例子&…

java编程字_Java编程基本概念

1.标识符①用于给变量、类和方法命名(类名首字母大写&#xff0c;变量和方法名首字母小写并遵循驼峰原则)②标识符的命名规范&#xff1a;■标识符必须以字母、下划线和美元符$开头。■标识符其他部分可以是字母、下划线、美元符和数字的任意组合。■Java标识符大小写敏感&…

ubuntu gedit出错:Failed to connect to the session manager

刚才用su到root后&#xff0c;用命令gedit发现会出错&#xff1a;** (gedit:2976): WARNING **: 连接已关闭(gedit:2976): EggSMClient-WARNING **: Failed to connect to the session manager:None of the authentication protocols specified are supported** (gedit:2976): …

php 类的实现 完整例子

文件目录&#xff1a; --index.php --php --data_info.php index.php 这里要require_once类所在的php文件 <?php require_once(./php/data_info.php);$oneDatanew user;$oneData->setName("username");$oneData->setPassword("password");echo $…

mac java版本 不一致_mac实现不同版本的jdk切换

之前使用jdk11进行java开发(纯粹因为喜欢新版?)但是使用jdk11在布署hadoop伪分布时各种报错, 所以还是下载jdk8回来.接下来就是mac端切换两个版本的jdk(按照网上找的方式好像有bug-文章最后再说.虽然不知道怎么解决,但是至少我可以成功部署hadoop, 所以这里就先忽略)首先下载j…

Meld安装

Ubuntu下文件/目录对比的软件Meld可能有很多用户还不是很熟悉&#xff0c;下文就给大家介绍如何安装Meld和移植到Gedit下。具体内容如下所述。 Meld允许用户查看文件、目录间的变化。很容易移植到Gedit下&#xff0c;方便用户使用。 安装Meld Meld默认在Ubuntu官方源中&#…

ios sqlite3 初级应用

ios sqlite3 初级应用 在ios中&#xff0c;持久化用好几种 方法&#xff0c;前面已经介绍了 两种 &#xff0c;一个是简单的写入文件&#xff0c;另一个是加入了序列化并写入文件中&#xff0c;现在介绍 ios 中嵌入式数据库sqlite3的初级应用 当然在使用sqlite3之前 你需要将l…