Multithreading 在Perl 6中运行自馈送通道
我想在一个通道上设置多个并发运行的线程,并且这些线程中的每一个都应该为通道提供数据。其中一个线程将决定何时停止。然而,这是我最近一次这样做:Multithreading 在Perl 6中运行自馈送通道,multithreading,concurrency,raku,Multithreading,Concurrency,Raku,我想在一个通道上设置多个并发运行的线程,并且这些线程中的每一个都应该为通道提供数据。其中一个线程将决定何时停止。然而,这是我最近一次这样做: use Algorithm::Evolutionary::Simple; my $length = 32; my $supplier = Supplier.new; my $supply = $supplier.Supply; my $channel-one = $supply.Channel; my $pairs-supply = $supply.
use Algorithm::Evolutionary::Simple;
my $length = 32;
my $supplier = Supplier.new;
my $supply = $supplier.Supply;
my $channel-one = $supply.Channel;
my $pairs-supply = $supply.batch( elems => 2 );
my $channel-two = $pairs-supply.Channel;
my $single = start {
react {
whenever $channel-one -> $item {
say "via Channel 1:", max-ones($item);
}
}
}
my $pairs = start {
react {
whenever $channel-two -> @pair {
my @new-chromosome = crossover( @pair[0], @pair[1] );
say "In Channel 2: ", @new-chromosome;
$supplier.emit( @new-chromosome[0]);
$supplier.emit( @new-chromosome[1]);
}
}
}
await (^10).map: -> $r {
start {
sleep $r/100.0;
$supplier.emit( random-chromosome($length) );
}
}
$supplier.done;
这在多次排放后停止。而且它可能不会同时运行。我使用通道而不是供给和抽头,因为它们不是并发运行的,而是异步运行的。我需要补给,因为我想有一个seudo通道,可以成对接收元素,如上所述;我还没见过用纯渠道做这件事的方法。
如果我将电源的emit
更改为通道的send
,则上面没有区别
这里有几个问题
react
块是否在不同的线程中运行?如果没有,那怎么做呢$pairs
一直向通道发射信号,它也会停止更新1:如果我从末尾删除
$supplier.done
,它将只是阻塞。如果我创建一个,每次读取一个,它只是阻塞,什么也不做 答案就在这里,精简到最低限度
my Channel $c .= new;
my Channel $c2 = $c.Supply.batch( elems => 2).Channel;
my Channel $output .= new;
my $count = 0;
$c.send(1) for ^2;
my $more-work = start react whenever $c2 -> @item {
if ( $count++ < 32 ) {
$c.send( @item[1]);
my $sum = sum @item;
$c.send( $sum );
$output.send( $sum );
} else {
$c.close;
}
}
await $more-work;
loop {
if my $item = $output.poll {
$item.say
} else {
$output.close;
}
if $output.closed { last };
}
my Channel$c.=new;
我的通道$c2=$c.Supply.batch(elems=>2.Channel);
我的频道$output.=新频道;
我的$count=0;
$c.send(1)用于^2;
my$more work=开始在$c2->@物品时作出反应{
如果($count++<32){
$c.send(@item[1]);
我的$sum=sum@项目;
$c.send($sum);
$output.send($sum);
}否则{
$c.close;
}
}
等待更多的工作;
环路{
如果我的$item=$output.poll{
$item.say
}否则{
$output.close;
}
如果$output.closed{last};
}
通过从一个通道($c.supply
)创建一个供应、将该供应分成两批(batch(elems=>2)
)并将其转换回一个通道,使用每两个元素对第一个通道进行批处理的第二个通道。为输出创建第三个通道。
为了不耗尽电源并挂起通道,从第一个(实际上是唯一的)通道读取的每一个第二个元素都被放回那里。所以第二个通道是两次读取,它永远不会被挂起或等待新元素。
为每个新元素创建一个输出通道,并在需要时创建一个外部计数器来完成操作;该输出通道以非阻塞方式读取,当最后一行中没有剩余内容可读取时关闭。
要准确回答我最初的问题:
您可以使用
start react where…{…}
而不是start{react{where…{…}}
以下是如何获得从另一个通道成对发射的通道:my channel$c.=new$c、 为^20发送($)$c、 接近;我的频道$c2.=新频道;my$work=start{$c2.send:$\$c.List.rotor(2);$c2.close;CATCH{default{$c2.fail($\}}。比如说c2.1美元;等待$work
-检查是否需要:转子呼叫也有部分。@BradGilbert没有区别。为什么效果更好?@timotimo这不是我想要的。如果我这样修改它,If($count++<100){$c.send($count);}else{$c.close;}
,这样它会继续向第一个通道馈电,而第二个通道则会在最初的20个数字之后挂起<代码>$count在此之前将被初始化为0。更接近我想要的,但仍然无法满足。它只是丢弃了一些对,并在处理第一个40@timotimo后停止