ruby - 学习Ruby线程-线程完成时触发事件

标签 ruby multithreading concurrency threadpool

我是多线程技术的新手,我正在寻找一些帮助,以帮助您理解线程完成后的惯用方式,例如更新进度条。在下面的示例中,我有一些项目和例程的列表,以对每个项目进行一些“解析”。我计划为每个列表提供一个进度条,因此我希望能够使每个列表的解析例程更新已完成项目的百分比。我看到的唯一“触发”点是在项困方法(被线程化的方法)末尾的puts语句处。捕获完成通常被接受的策略是什么,特别是当操作的范围超出线程中运行的方法的范围时?
谢谢!

# frozen_string_literal: true

require 'concurrent'

$stdout.sync = true

class TheList
  attr_reader :items

  def initialize(list_id, n_items)
    @id = list_id
    @items = []
    n_items.times { |n| @items << Item.new(@id, n) }
  end

  def parse_list(pool)
    @items.each do |item|
      pool.post { item.sleepy(rand(3..8)) }
    end
  end
end

class Item
  attr_reader :id

  def initialize (list_id, item_id)
    @id = item_id
    @list_id = list_id
  end

  def sleepy(seconds)
    sleep(seconds)
    # This puts statement signifies the end of the method threaded
    puts "List ID: #{@list_id} item ID:#{@id} slept for #{seconds} seconds"
  end
end

lists = []
5.times do |i|
  lists << TheList.new(i, rand(5..10))
end

pool = Concurrent::FixedThreadPool.new(Concurrent.processor_count)

lists.each do |list|
  list.parse_list(pool)
end
pool.shutdown
pool.wait_for_termination

最佳答案

问题并不是真正的“知道线程何时完成”,而是如何在没有竞争条件的情况下更新共享进度栏。
解释这个问题:假设您有一个中央ThreadList#progress_var变量,并且作为每个线程的最后一行,您使用+=对其进行了递增。因为两个线程可以同时执行该操作(并且可能覆盖彼此的结果),所以这会引入竞争条件。
为了解决这个问题,典型的方法是使用Mutex,这是了解您是否正在学习多线程的基本概念。
实际的实现并不困难:

require 'mutex'

class ThreadList
  def initialize
    @semaphore = Mutex.new   
    @progress_bar = 0
  end
  def increment_progress_bar(amount)
    @semaphore.synchronize do
      @progress_bar += amount
    end
  end 
end
由于存在@semaphore.synchronize块,因此您现在可以从线程中安全地调用此increment_progress_bar方法,而不必担心出现竞争状况。

关于ruby - 学习Ruby线程-线程完成时触发事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65376347/

相关文章:

ruby - 正则表达式任何非数字有异常(exception)

c# - 连续执行的多线程 WebRequests

multithreading - Hibernate的线程问题

java - 我在理解并发文档时遇到问题

c# - 使用线程安全更新单例的属性

c++ - 在 C++ 中具有明确定义的分配器的危险指针

ruby - 如何在 Ruby 中获取 UTC 时间戳?

ruby - 是否有类似于 Nokogiri 的东西来解析 Ruby 代码?

ruby-on-rails - 如何将查询参数放在_pathrails_helper上

multithreading - 哪个更有效,基本互斥锁或原子整数?