如何实现跟踪输入流字符出现次数的并发流通信程序?
解决方案:并发字符计数跟踪程序
首先,你的ConcMap存在核心问题:每个线程拿到的累积值A是独立的旧状态,没有共享的全局计数容器,导致输出的是单个元素的倒序拼接,而非累积的字符计数。要实现需求,需要共享可变状态来维护计数,并保证状态更新的线程安全性,同时按输入流顺序处理元素(因为计数依赖前序状态)。
核心思路
- 使用
Cell(Oz语言的可变容器)存储字符计数字典,确保所有处理逻辑共享同一状态。 - 遍历输入流时,逐个更新共享计数,并生成格式化的输出流元素。
- 并发体现在处理流的线程与浏览输出的线程并行,而非元素之间的并行(避免计数竞争)。
修正后的代码实现
declare % 更新共享计数:传入存储计数的Cell和当前字符,更新后返回最新计数 fun {UpdateCount CountCell Char} CurrentCounts = {CountCell.get} % 计算字符的新计数 NewCount = case {Lookup CurrentCounts Char} of nil then 1 [] Existing then Existing + 1 end % 更新Cell中的字典 {CountCell.put {Record.extend CurrentCounts Char#NewCount}} % 返回最新计数用于生成输出 {CountCell.get} end % 将计数字典格式化为期望的字符串(如"a#1 b#1") fun {FormatCounts CountDict} % 遍历字典的所有键,生成"键#值"的字符串列表 KeyCountStrs = {Map {Record.fields CountDict} fun {$ Key} Key#${Lookup CountDict Key} end} % 拼接成带括号的最终格式 "["{String.concat KeyCountStrs " "}"]" end % 处理输入流,生成计数输出流 fun {TrackCharStream InS CountCell} case InS of nil then nil [] Char|Rest then % 更新计数并获取最新状态 LatestCounts = {UpdateCount CountCell Char} % 生成当前输出元素,递归处理剩余流 {FormatCounts LatestCounts}|{TrackCharStream Rest CountCell} end end % 测试代码 local InS OutS CountCell in InS = a|b|a|c|_ % 输入惰性流 CountCell = {Cell.new record()} % 初始化空计数字典的Cell % 启动线程处理流,避免阻塞主线程 thread OutS = {TrackCharStream InS CountCell} end {Browse OutS} % 输出:[a#1]|[a#1 b#1]|[a#2 b#1]|[a#2 b#1 c#1]|_ end
原代码问题解析
你的ConcMap中,每个线程接收的A是X|A(当前元素加旧列表),这意味着每个线程操作的是独立的局部状态,而非共享的全局计数。这种设计无法实现累积计数,只能生成每个元素的倒序拼接列表。
关于输入流InS的说明
Oz中a|b|a|c|_是惰性流,_表示未绑定的尾变量,可用于模拟持续输入(如用户输入、文件流等)。处理时会按顺序逐个解析流元素,直到遇到绑定的nil或流结束。
内容的提问来源于stack exchange,提问作者scsi
相关产品推荐
相关产品推荐

