惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
V
Visual Studio Blog
博客园 - 三生石上(FineUI控件)
Last Week in AI
Last Week in AI
Blog — PlanetScale
Blog — PlanetScale
爱范儿
爱范儿
J
Java Code Geeks
A
About on SuperTechFans
F
Fortinet All Blogs
B
Blog
aimingoo的专栏
aimingoo的专栏
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Engineering at Meta
Engineering at Meta
Y
Y Combinator Blog
有赞技术团队
有赞技术团队
G
Google Developers Blog
Apple Machine Learning Research
Apple Machine Learning Research
V
V2EX
博客园_首页
博客园 - 叶小钗
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
Docker
云风的 BLOG
云风的 BLOG

博客园 - YD

如何查找某一函数的定义 Ruby的函数指针 Rails2.0学习--真困难 加班赶工,得不偿失——历史给你上六课 7. 创建Subversion服务之补充 Task Manager 1.1 开源软件:(Task Manager)任务管理-找出自己最需要完成的任务 小说阅读器 2.0 6. 创建 Subversion 服务 小说阅读器,有兴趣的同志可以试一下 不规则窗体的制作 播放 wave 文件 简单 Socket 通信 CRC 校验 C# 实现法 5. 多人协作 C# 中信号量的使用 4. 不要把不必要的文件版本化 3. 从 Repository 中恢复 2. 创建你的 Repository
Ruby 线程--生产者、消费者
YD · 2008-05-25 · via 博客园 - YD

今天看了Ruby的线程部分。《Programming Ruby》第一版的HTML版的线程和进程部分讲得很详细。看完后感觉就好像又把操作系统的这一部分重温了一遍。尤其是Spawning New Processes那一节,如果没有学过操作系统还真不知道他说什么。

IO.popen,其中的popen,我理解应该是应该是"piped open"的意思。其中这段代码,

pipe = IO.popen("-","w+")
if pipe
  pipe
.puts "Get a job!"
  
$stderr.puts "Child says '#{pipe.gets.chomp}'"
else
  
$stderr.puts "Dad says '#{gets.chomp}'"
  puts 
"OK"
end

简直和Unix课里面的fork代码示例一样,父子进程共享同一段代码。《Programming Ruby》对这段代码的解释是“There's one more twist to popen. If the command you pass it is a single minus sign (``--''), popen will fork a new Ruby interpreter. Both this and the original interpreter will continue running by returning from the popen. The original process will receive an IO object back, while the child will receive nil. ”。第一次看我完全没看出来他说的是什么。看了代码后一时间也没往fork去想。结果过了十分钟后灵光一现才知道是怎么回事。同志们,看英文的东西不容易啊!

线程还挺好学。Ruby线程的功能是自已实现的。与操作系统无关。为了达到平台无关性,这种牺牲我觉得有点大。不说作者开发时得费多少力气。就是使用起来,也没有本地线程的种种优势。比如说线程饥饿。下面我写了一个练习性质的生产者--消费者例子。实话说,比Ruby中thread.rb里的例子要长太多……好处是,这里解决了屏幕输出时的窜行问题。

require 'thread'

class Consumer
  def initialize
(queue, stdout_mutex)
    @queue 
= queue
    @stdout_mutex 
= stdout_mutex
  
end
  
  def consume
    product 
= @queue.pop
    @stdout_mutex
.synchronize {
      puts 
"Product #{product} consumed."
      
$stdout.flush
    }
  
end
end

class Producer
  def initialize
(queue, stdout_mutex)
    @queue 
= queue
  
end
  
  def produce
    product 
= rand(10)
    @queue
.push(product)
    @stdout_mutex
.synchronize {
      puts 
"Product #{product} produced."
      
$stdout.flush
    }
  
end
end

sized_queue 
= SizedQueue.new(10)
stdout_mutex 
= Mutex.new
consumer_threads 
= []

100.times {
  consumer_threads 
<< Thread.new {
    consumer 
= Consumer.new(sized_queue, stdout_mutex)
    consumer
.consume
  }
  
  Thread
.new {
    producer 
= Producer.new(sized_queue, stdout_mutex)
    producer
.produce
  }
}

consumer_threads
.each { |thread| thread.join }