Как правильно завершить все потоки, которые подчинены основной - PullRequest
0 голосов
/ 03 мая 2019

Я запускаю несколько потоков, и когда один из потоков устанавливает для глобальной функции ' $ trade_executed ' значение true, я хочу, чтобы она уничтожила все другие потоки и удалила их из глобальной ' $. массив потоков .

Затем я перезапускаю процесс создания потока.

Ниже приведена упрощенная версия моей кодовой базы.

3 Потоки созданы, и похоже, что 2 потока удалены, но третий поток остается. (по неизвестным причинам)

В идеале этот скрипт никогда не будет печатать «2» или «3», потому что он всегда будет срабатывать в «1» минуту, уничтожать все потоки и сбрасываться.

* thr.exit является предпочтительным. Я не хочу, чтобы какой-либо код выдвигался из других потоков с thr.join после того, как $ trade_executed установлено

require 'thread'

class Finnean 
  def initialize
    @lock = Mutex.new
  end

  def digger(minute)  
    sleep(minute * 60)
    coco(minute)
  end 

  def coco(minute)  
    @lock.synchronize {
    puts "coco #{minute}"

      $threads.each do |thr|
      next if thr == Thread.current
      thr.exit
      end
      $trade_executed = true
      Thread.current.exit   
    } 
  end 
end

minutes = [1, 2, 3]
$threads = Array.new 
$trade_executed = false 
abc = Finnean.new

def start_threads(minutes, abc)
  minutes.each do |minute|
    $threads << Thread.new {abc.digger(minute)}
    puts minute
  end
end

start_threads(minutes, abc)

while true
  if $trade_executed != false then 
    count = 0
    $threads.map! do |thr|
      count += 1
      puts "#{thr} & #{thr.status}"
      thr.exit
      $threads.delete(thr)
      puts "Iteration #{count}"
    end

    count = 0
    $threads.each do |thr|
      count += 1
      puts "#{thr}" ##{thr.status}
      puts "Threads Still Left: #{count}"
    end            

    $trade_executed = false
    abc = Finnean.new
    start_threads(minutes, abc)
  end
end

1 Ответ

0 голосов
/ 04 мая 2019

Почему бы не сделать прерыватель потока, который вы держите взаперти, пока не закончится первый:

# Create two variables that can be passed in to the Thread.new block closure
threads = [ ]
killer = nil

# Create 10 threads, each of which waits a random amount of time before waking up the thread killer
10.times do |n|
  threads << Thread.new do
    sleep(rand(2..25))

    puts "Thread #{n} finished!"
    killer.wakeup
  end
end

# Define a thread killer that will call `kill` on all threads, then `join`
killer = Thread.new(threads) do
  Thread.stop

  threads.each do |thread|
    puts "Killing #{thread}"
    thread.kill
    thread.join
  end
end

# The killer will run last, so wait for that to finish
killer.join

Вы не можете принудить поток к exit, но вы можете убить его. Это генерирует исключение, которое вы можете rescue и обрабатывать по мере необходимости.

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