首页 > 解决方案 > 如何使 ruby​​ API 调用和 CSV 编写线程安全?

问题描述

我正在尝试构建一个读取大型 CSV 文件的程序,然后同时将请求发送到 API 端点,最后将结果存储到另一个 CSV 文件。我已在此页面https://blog.engineyard.com/ruby-thread-pool上阅读了有关线程池的信息,还发现了有关并发 ruby​​ gem 的信息。我认为我想要实现的目标应该很容易在不使用 gem 的情况下实现。我正在使用 MRI 解释器并阅读有关 GIL 的信息。我认为由于这似乎是 IO 重,我不需要使用 Jruby 和诸如桃子之类的宝石。这是我到目前为止所拥有的:

array_of_stuff = CSV.read("#{file_name}")

work_q = Queue.new

array_of_stuff.flatten.each { |x| work_q .push x }

workers = (0..4).map do 

 Thread.new { 
            begin 
            while item = work_q.pop(true) 

            uri = URI.parse("https://website.com/query=" + "#{item}")
            #create the HTTP protocol 
            http = Net::HTTP.new(uri.host, uri.port)
            #set up ssl 
            http.use_ssl = true 
            http.verify_mode = OpenSSL::SSL::VERIFY_NONE

            #create the request 
            req = Net::HTTP::Get.new(uri)
            req["Authorization"] = "Special #{token}"

            #create the response 
            response = http.request(req)

            if response.body == "[]\n"
            print "\nNo data for #{item}\n"
            next 
            end 

            #parse JSON response.
            data = JSON.parse(response.body) 

            puts "#{item} has some data #{data[0]["Attribute"]["value"]}"

                 print "\Storing results to a CSV file.\n"
                 CSV.open("item_store.csv", "a+") do |csv|
                 csv << ["#{item}", "#{data[0]["Attribute"]["value"]}"]
                 end 
            end 
            rescue ThreadError
            end 
   }
end 

workers.map(&:join) 

我知道这不起作用,因为puts代码部分向我显示某些请求已多次发出。我已经阅读了互斥同步并尝试过,但它减慢了我的代码速度,而且我使用错了。如果有人可以帮助我并消除我的误解,我将不胜感激!

标签: rubymultithreadingcsvthread-safety

解决方案


推荐阅读