如何在Ruby中运行后台线程?

8

我是新手,想用Ruby重建一个我以前用C#编写的简单聊天程序。

我使用的是Ruby 2.0.0 MRI(Matz的Ruby实现)。

问题在于我希望在服务器运行时拥有简单的服务器命令I/O。这是从示例中获取的服务器。我添加了使用gets()获取输入的commands方法。我希望这个方法在后台作为线程运行,但该线程正在阻塞其他线程。

require 'socket'                # Get sockets from stdlib

server = TCPServer.open(2000)   # Socket to listen on port 2000

def commands
    x = 1
    while x == 1
        exitProgram = gets.chomp
        if exitProgram == "exit" || exitProgram == "Exit"
            x = 2
            abort("Exiting the program.")
        end
    end
end

def main
    Thread.start(commands)
    Thread.start(server.accept) 
    loop {                          # Servers run forever

        Thread.start(server.accept) do |client|
        client.puts(Time.now.ctime) # Send the time to the client
        client.puts "Closing the connection. Bye!"
        client.close                # Disconnect from the client
      end
    }
end

main

这是目前的客户端。
require 'socket'      # Sockets are in standard library

hostname = 'localhost'
port = 2000

s = TCPSocket.open(hostname, port)

while line = s.gets   # Read lines from the socket
  puts line.chop      # And print with platform line terminator
end
s.close               # Close the socket when done
gets.chomp

你在使用MRI Ruby还是JRuby?这是在Rails中吗?这对线程有影响。我不认为MRI具有本地线程。 - seand
谢谢,那我想我会转换到另一个 Ruby 版本,除非有一个非阻塞版本的 gets() 函数? - user3081457
JRuby拥有真正的线程。它可能适合你,但启动时间非常糟糕。(我因此取消了一个以上的项目中的JRuby)。如果你在Rails中运行,请小心,因为很多Rails不是线程安全的。 - seand
谢谢!我可能会选择使用JRuby,因为我并没有做一个需要Rails的Web项目。 - user3081457
2
你不需要使用JRuby。MRI对于聊天服务器来说已经足够了。GIL并不会阻止多连接。例如,Node.js是单线程的,但可以处理高并发请求。你不必手动编写线程,eventmachine就是为此而设计的。该页面上有一个EchoServer示例。 - user1375096
显示剩余5条评论
1个回答

12

阅读Thread.new的文档(这里与Thread.start相同)

Thread.start(commands)运行commands方法并将其返回值传递给一个线程(然后什么都不做)。它是阻塞的,因为在调用gets时没有启动任何线程。您需要

Thread.start { commands }

这是一个类似的演示脚本,它的工作方式就像您所期望的那样。

def commands
  while gets.strip !~ /^exit$/i
    puts "Invalid command"
  end
  abort "Exiting the program"
end

Thread.start { commands }

loop do
  puts "Type exit:"
  sleep 2
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接