7

ファイバー\コルーチンの背後にあるアイデアとCrystalでの実装を学ぶのに苦労しています。

私はこれがこれを尋ねる適切な場所であることを願っています.「ここにいない」という答えを完全に受け入れます:)

これは、Ruby でマルチスレッドを処理する私の通常の方法です。

threads = []
max_threads = 10

loop do
  begin
    threads << Thread.new do
      helper_method(1,2,3,4)
    end
  rescue Exception => e
    puts "Error Starting thread"
  end

  begin
    threads = threads.select { |t| t.alive? ? true : (t.join; false) }
    while threads.size >= max_threads
      puts 'Got Maximum threads'
      sleep 1
      threads = threads.select { |t| t.alive? ? true : (t.join; false) }
    end
  rescue Exception => e
    puts e
  end
end

このようにして、通常は着信接続などの新しいスレッドを開き、スレッドをスレッド配列に追加してから、必要以上のスレッドがないことを確認します。

spawn\channels\fibers などを使用して、Crystal で同様のものを実装するにはどうすればよいでしょうか。

4

2 に答える 2

15

このようなもの:

require "socket"

ch = Channel(TCPSocket).new

10.times do
  spawn do
    loop do
      socket = ch.receive
      socket.puts "Hi!"
      socket.close
    end
  end
end

server = TCPServer.new(1234)
loop do
  socket = server.accept
  ch.send socket
end

このコードは、リクエストに対応するために 10 個のファイバーを事前に生成します。チャネルはバッファリングされていないため、ファイバーが接続できない場合、接続はキューに入れられません。

于 2015-06-15T20:05:45.157 に答える
6

スレッドで機能する方法を複製することはできません。spawnはコルーチン オブジェクトを返さず、コルーチンへの方法もありませんjoin

それでも、コルーチンとプール マネージャーの間で通信するためのチャネルを開くことができます。このマネージャーは、独自のコルーチン内で実行されるか、メインのコルーチンになる可能性があります。これにより、プロセスが終了するのを防ぎます。

worker(&block)コルーチンを生成し、チャネルを開いてそのステータス (失敗または終了) を返すpool(&block)メソッドと、そのようなワーカーのプールを保持し、結果チャネルから読み取って知るメソッドを使用した実際の例を次に示します。コルーチンの状態を確認し、新しいものを生成し続けます。

def worker(&block)
  result = UnbufferedChannel(Exception?).new

  ::spawn do
    begin
      block.call
    rescue ex
      result.send(ex)
    else
      result.send(nil)
    end
  end

  result
end

def pool(size, &block)
  counter = 0
  results = [] of UnbufferedChannel(Exception?)

  loop do
    while counter < size
      counter += 1
      puts "spawning worker"
      results << worker(&block)
    end

    result = Channel.select(results)
    counter -= 1
    results.delete(result)

    if ex = result.receive
      puts "ERROR: #{ex.message}"
    else
      puts "worker terminated"
    end
  end
end

pool(5) do
  loop { helper_method(1, 2, 3, 4) }
end
于 2015-06-15T21:55:33.767 に答える