代码之家  ›  专栏  ›  技术社区  ›  qpi

Crystal lang.如何通过少数生产商实现图案生产商-消费者?

  •  1
  • qpi  · 技术社区  · 7 年前

    几天前我问 Does it have a crystal-lang Queue? ,而@Johannes Mller回答我使用 Channel::Buffered(T) . 现在,我有一个小小的另一个问题。如果我有多个制作人怎么办?所有人都使用相同的 Channel ?

    例如:

    channel = Channel(String).new
    
    # first producer
    spawn do
      5.times do |i|
        puts "first producer #{i}"
        channel.send "first #{i}"
        sleep 0.1
      end
    end
    
    # second producer, that send data to the same with first producer channel
    spawn do
      5.times do |i|
        puts "second producer #{i}"
        channel.send "second #{i}"
        sleep 0.1
      end
    end
    
    # consumer
    spawn do
      loop do
        data = channel.receive
        puts "receive: #{data}"
        sleep 0.5
      end
    end
    
    sleep 6
    

    输出将为:

    $ crystal ./test.cr
    first producer 0 # ok. first produced 0
    second producer 0 # ok. second produced 0
    receive: first 0 # ok. received from the first producer
    first producer 1 # o_O. Where received data from the second producer?
    receive: first 1 
    first producer 2
    receive: first 2
    first producer 3
    receive: first 3
    first producer 4
    receive: first 4
    receive: second 0 # aa. It's here... Why it's happend only, when the first producer was produced all?
    second producer 1 
    receive: second 1
    second producer 2
    receive: second 2
    second producer 3
    receive: second 3
    second producer 4
    receive: second 4
    

    正如您所见,“第二个制作人”几乎与第一个同时发送第一个包,但直到第一个制作人完成工作之前,它都被忽略了。不管通道是否已缓冲。

    为什么他们没有始终如一地工作?如果第一个生产者以一个永恒的周期工作,则从未收到来自第二个生产者的数据。

    也许这种行为应该是这样的,并将数据从几个地方发送到一个地方-显然是不好的做法?

    1 回复  |  直到 7 年前
        1
  •  2
  •   Community frankie liuzzi    4 年前

    Read the docs!

    不确定我是否正确理解了你的意思,但这是预期的结果吗

    First producer sent: 0
    Consumer received "First: 0"!
    Second producer sent: 0
    Consumer received "Second: 0"!
    First producer sent: 1
    Consumer received "First: 1"!
    Second producer sent: 1
    Consumer received "Second: 1"!
    First producer sent: 2
    Consumer received "First: 2"!
    Second producer sent: 2
    Consumer received "Second: 2"!
    First producer sent: 3
    Consumer received "First: 3"!
    Second producer sent: 3
    Consumer received "Second: 3"!
    First producer sent: 4
    Consumer received "First: 4"!
    Second producer sent: 4
    Consumer received "Second: 4"!
    

    如果有;代码如下:

    class CrystalIsAwesome
      @@products = 0
      @@channel = Channel(String).new
    
      def self.produce(which, times, produce_time = 0)
        @@products += times
        spawn do
          times.times do |i|
            puts "#{which} producer sent: #{i}"
            @@channel.send "#{which}: #{i}"
            sleep produce_time.seconds
            end
        end
      end
    
      # first producer
      produce "First", 5
    
      # second producer
      produce "Second", 5
    
      @@products.times do |_|
        puts %(Consumer received "#{@@channel.receive}"!)
      end
    end
    

    尝试添加第三个制作人( produce "Third", 2, 1 )看看结果如何。

    再一次看见 the Concurrency docs 为什么会这样。