Ruby пронизывает управление передачей на главную - PullRequest
0 голосов
/ 29 октября 2010

Я программирую приложение на Ruby, которое создает новый поток для каждой новой работы.Так что это похоже на администратор очередей, где я проверяю, сколько потоков можно запустить из базы данных.Теперь, когда поток заканчивается, я хочу вызвать метод, чтобы начать новое задание (т.е. новый поток).Я не хочу создавать вложенные потоки, так есть ли способ присоединиться / завершить / выйти из вызывающего потока и передать управление основному потоку?Просто чтобы прояснить ситуацию, в это время могут выполняться другие потоки.

Я попытался просто присоединиться к вызывающему потоку, если это не основной поток, и я получаю следующую ошибку;

Любые предложения будут высоко оценены.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 29 октября 2010
t1 = Thread.new { Thread.current[:status] = "1"; sleep 10; Thread.pass; sleep 100 }  
t2 = Thread.new { Thread.current[:status] = "2"; sleep 1000 }  
t3 = Thread.new { Thread.current[:status] = "3"; sleep 1000 }  

puts Thread.list.map {|X| x[:status] }
#=> 1,2,3

Thread.list.each do |x| 
  if x[:status] == 2 
    x.kill # kill the thread
    break
  end
end  

puts Thread.list.map {|X| x[:status] }
#=> 1,3

"Thread :: pass" передаст управление планировщику, который теперь может планировать любой другой поток.Поток добровольно передал управление планировщику - мы не можем указать передачу управления определенному потоку

"Thread # kill" уничтожит экземпляр потока

"Thread :: list"вернет список потоков

Потоки управляются планировщиком, если вы хотите явное управление, тогда извлекайте волокна.Но у него есть некоторые ошибки, волокна не поддерживаются в JRuby.

также извлекает локальные переменные потока, это поможет вам сообщить состояние или возвращаемое значение потока, не присоединяясь к потоку.

http://github.com/defunkt/resque - хороший вариант для очереди, проверьте его.Также попробуйте JRuby, если вы собираетесь интенсивно использовать потоки.Преимущество состоит в том, что он обернет нити Java в рубиновую доброту.

0 голосов
/ 29 октября 2010

Я бы предложил два решения:

первое - это эффективное объединение в потоке, но соединение должно вызываться из основного потока (при условии, что вы запустили все свои рабочие потоки из основного):

def thread_proc(s)
  sleep rand(5)
  puts "#{Thread.current.inspect}: #{s}"
end

strings = ["word", "test", "again", "value", "fox", "car"]

threads = []
2.times { 
  threads << Thread.new(strings.shift) { |s| thread_proc(s) }
}

while !threads.empty?
  threads.each { |t|
    t.join
    threads << Thread.new(strings.shift) { |s| thread_proc(s) } unless strings.empty?
    threads.delete(t)
  }
end

но этот метод неэффективен, потому что создание потоков снова и снова приводит к перегрузке памяти и ЦП.

Вы должны лучше синхронизировать фиксированный пул повторно используемых потоков, используя Очередь:

require 'thread'

strings = ["word", "test", "again", "value", "fox", "car"]

q = Queue.new
strings.each { |s| q << s }

threads = []
2.times { threads << Thread.new {
  while !q.empty?
    s = q.pop
    sleep(rand(5))
    puts "#{Thread.current.inspect}: #{s}"
  end
}}

threads.each { |t| t.join }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...