Рубин Многопоточность
Каждая программа, работающая на системе является процессом. Каждый процесс содержит один или несколько потоков.
Поток представляет собой единый последовательный поток управления программой, одновременно запускать несколько потоков в одной программе делать разные вещи, называемые многопоточность.
Рубин, мы можем быть созданы несколько классов темы, Ruby нити легкий, он может быть эффективным способом для реализации параллельного кода.
Создание потока на Ruby
Чтобы начать новую тему, вы можете просто позвонить Thread.new:
# 线程 #1 代码部分 Thread.new { # 线程 #2 执行代码 } # 线程 #1 执行代码
примеров
В следующем примере показано, как использовать многопоточность в программе Ruby:
#!/usr/bin/ruby def func1 i=0 while i<=2 puts "func1 at: #{Time.now}" sleep(2) i=i+1 end end def func2 j=0 while j<=2 puts "func2 at: #{Time.now}" sleep(1) j=j+1 end end puts "Started At #{Time.now}" t1=Thread.new{func1()} t2=Thread.new{func2()} t1.join t2.join puts "End at #{Time.now}"
Приведенный выше код выполняется в результате:
Started At Wed May 14 08:21:54 -0700 2014 func1 at: Wed May 14 08:21:54 -0700 2014 func2 at: Wed May 14 08:21:54 -0700 2014 func2 at: Wed May 14 08:21:55 -0700 2014 func1 at: Wed May 14 08:21:56 -0700 2014 func2 at: Wed May 14 08:21:56 -0700 2014 func1 at: Wed May 14 08:21:58 -0700 2014 End at Wed May 14 08:22:00 -0700 2014
Жизнь Тема цикла
1, создать поток может использовать Thread.new, вы также можете использовать один и тот же синтаксис Thread.start или Thread.fork три способа создания потока.
2, создать поток без запуска, поток будет выполняться автоматически.
3, класс резьбы определяет методы для манипулирования нить. Тема блоков кода выполнения Thread.new.
4, блок нить значение последнего оператора в потоке, поток может быть вызван методом, если поток завершается, он возвращает значение потока, или не возвращает значение, пока поток не будет закончена.
5, метод Thread.current возвращает объект для текущего представления потоков. Thread.main метод возвращает основной поток.
6, способ осуществляют с помощью Thread.join нитей, этот метод будет приостановить основной поток, пока текущий поток не будет закончена.
Государство Thread
Тема имеет пять состояний:
Государство Thread | Возвращаемое значение |
---|---|
исполнимый | пробег |
спальный | спальный |
выход | прерывании |
Нормальное завершение | ложный |
Аварийное завершение происходит | ноль |
Нитки и аберрантное
Когда происходит исключение нити, и никакого спасения не был взят в плен, то поток, как правило, прекращается без предупреждения. Однако, если другие темы # присоединиться, потому что отношения ждали этой темы, то ожидающие потоки также будет поднята то же исключение.
begin t = Thread.new do Thread.pass # 主线程确实在等join raise "unhandled exception" end t.join rescue p $! # => "unhandled exception" end
Используйте следующие три метода, вы можете получить интерпретатор, чтобы прервать операцию, когда поток завершается из-за исключения.
- Запуск сценария определяет параметр-d, и работу в режиме отладки.
- С
Thread.abort_on_exception
установить флаг. - Использование
Thread#abort_on_exception
указанный набор нить флаг.
При использовании одного из трех способов, описанных выше, весь интерпретатор будет прервана.
t = Thread.new { ... } t.abort_on_exception = true
Синхронизация потоков
В Ruby, обеспечивает три синхронизированным образом, а именно:
1. Класс Mutex реализует синхронизацию потоков
2. Нормативная передачи данных класса Queue осуществить синхронизацию потоков
Контроль синхронизации 3. Используйте ConditionVariable
По Mutex класс реализует синхронизацию потоков
По классу Mutex реализует контроль синхронизации потоков, если вам также нужна переменная часы программы в несколько потоков, вы можете использовать замок для блокировки переменной части. Код выглядит следующим образом:
#!/usr/bin/ruby require "thread" puts "Synchronize Thread" @num=200 @mutex=Mutex.new def buyTicket(num) @mutex.lock if @num>=num @num=@num-num puts "you have successfully bought #{num} tickets" else puts "sorry,no enough tickets" end @mutex.unlock end ticket1=Thread.new 10 do 10.times do |value| ticketNum=15 buyTicket(ticketNum) sleep 0.01 end end ticket2=Thread.new 10 do 10.times do |value| ticketNum=20 buyTicket(ticketNum) sleep 0.01 end end sleep 1 ticket1.join ticket2.join
Приведенный выше код выполняется в результате:
Synchronize Thread you have successfully bought 15 tickets you have successfully bought 20 tickets you have successfully bought 15 tickets you have successfully bought 20 tickets you have successfully bought 15 tickets you have successfully bought 20 tickets you have successfully bought 15 tickets you have successfully bought 20 tickets you have successfully bought 15 tickets you have successfully bought 20 tickets you have successfully bought 15 tickets sorry,no enough tickets sorry,no enough tickets sorry,no enough tickets sorry,no enough tickets sorry,no enough tickets sorry,no enough tickets sorry,no enough tickets sorry,no enough tickets sorry,no enough tickets
В дополнение к использованию замок заперт переменной, вы можете также использовать try_lock запертую переменную, вы можете также использовать Mutex.synchronize синхронизации доступа к конкретной переменной.
Нормативная передачи данных класса Queue реализует синхронизацию потоков
класс Queue, который представляет собой очередь поддержки потоков, очередь может быть синхронизирован с конца визита. Различные потоки могут использовать единый класс, но не беспокойтесь о том, являются ли данные могут быть синхронизированы в этой очереди, кроме того, чтобы ограничить использование длины очереди класса SizedQueue
SizedQueue класс может быть очень удобно, чтобы помочь нам в разработке многопоточных приложений для синхронизации, проблемы синхронизации должны быть добавлены к длинной очереди, вы не заботитесь о потоках.
Классические производители и потребители:
#!/usr/bin/ruby require "thread" puts "SizedQuee Test" queue = Queue.new producer = Thread.new do 10.times do |i| sleep rand(i) # 让线程睡眠一段时间 queue << i puts "#{i} produced" end end consumer = Thread.new do 10.times do |i| value = queue.pop sleep rand(i/2) puts "consumed #{value}" end end consumer.join
Вывод программы:
SizedQuee Test 0 produced 1 produced consumed 0 2 produced consumed 1 consumed 2 3 produced consumed 34 produced consumed 4 5 produced consumed 5 6 produced consumed 6 7 produced consumed 7 8 produced 9 produced consumed 8 consumed 9
Переменные темы
Тема может иметь свою частную переменную, поток частной переменной поток записи, когда создается поток. Он может быть использован в пределах нити, но нить не может совместно использоваться наружно.
Но иногда, нить локальные переменные не нужно на другой поток или основной поток, чтобы получить доступ, как это сделать? рубин позволяет им создавать поток обеспечивается именем переменной, поток рассматривается как подобный стиль хэш хэш-таблицы. Согласно [] = написан [] читать данные. Мы смотрим на следующий код:
#!/usr/bin/ruby count = 0 arr = [] 10.times do |i| arr[i] = Thread.new { sleep(rand(0)/10.0) Thread.current["mycount"] = count count += 1 } end arr.each {|t| t.join; print t["mycount"], ", " } puts "count = #{count}"
Приведенный выше код выполняется выход:
8, 0, 3, 7, 2, 1, 6, 5, 4, 9, count = 10
Основной поток ожидает выполнение дочернего потока завершается, а затем выводит каждое значение. ,
приоритет резьбы
Приоритет потока является основным фактором, влияющим на планирование потоков. Другие факторы включают в себя интервал времени, чтобы выполнить планирование пакетов ЦП-потоков и так далее.
Вы можете использовать Thread.priority получают приоритет нити и использовать Thread.priority = метод, чтобы настроить приоритет потока.
приоритета по умолчанию волоске до 0. Быстрее исполнение с более высоким приоритетом.
Поток может получить доступ ко всем данным в пределах своих собственных, но если есть другие потоки должны получить доступ к данным в потоке должно быть, как это сделать? класс резьбы предоставляет данные потоков доступ друг к другу, вы можете просто положить нить в качестве хэш-таблицы, могут быть использованы в любом потоке [] = данные писать, использовать [] читать данные.
athr = Thread.new { Thread.current["name"] = "Thread A"; Thread.stop } bthr = Thread.new { Thread.current["name"] = "Thread B"; Thread.stop } cthr = Thread.new { Thread.current["name"] = "Thread C"; Thread.stop } Thread.list.each {|x| puts "#{x.inspect}: #{x["name"]}" }
Мы можем видеть, нить в качестве хэш-таблицу, используйте [] и [] = метод, мы достигли совместного использования данных между потоками.
мьютекс резьбы
Mutex (Муталь = Исключение мьютекс) представляет собой метод многопоточного программирования, механизм для предотвращения двух потоков одновременно для одних и тех же государственных ресурсов (например, глобальные переменные) читать и писать.
Примеры неиспользуемом Mutax
#!/usr/bin/ruby require 'thread' count1 = count2 = 0 difference = 0 counter = Thread.new do loop do count1 += 1 count2 += 1 end end spy = Thread.new do loop do difference += (count1 - count2).abs end end sleep 1 puts "count1 : #{count1}" puts "count2 : #{count2}" puts "difference : #{difference}"
Запуск в приведенном выше примере выход:
count1 : 9712487 count2 : 12501239 difference : 0
Пример Mutax
#!/usr/bin/ruby require 'thread' mutex = Mutex.new count1 = count2 = 0 difference = 0 counter = Thread.new do loop do mutex.synchronize do count1 += 1 count2 += 1 end end end spy = Thread.new do loop do mutex.synchronize do difference += (count1 - count2).abs end end end sleep 1 mutex.lock puts "count1 : #{count1}" puts "count2 : #{count2}" puts "difference : #{difference}"
Запуск в приведенном выше примере выход:
count1 : 1336406 count2 : 1336406 difference : 0
тупик
Более двух оперативных подразделений, обе стороны ждут другого, чтобы остановить бег, чтобы получить системные ресурсы, но не партийную ранний выход, эта ситуация называется тупиковой.
Например, p1 процесс занимает дисплей, в то время как вы должны использовать принтер, и принтер занят процессом р2, р2 должны также использовать монитор, тем самым образуя затор.
Когда мы используем мьютекс объект требует внимания нити тупика.
примеров
#!/usr/bin/ruby require 'thread' mutex = Mutex.new cv = ConditionVariable.new a = Thread.new { mutex.synchronize { puts "A: I have critical section, but will wait for cv" cv.wait(mutex) puts "A: I have critical section again! I rule!" } } puts "(Later, back at the ranch...)" b = Thread.new { mutex.synchronize { puts "B: Now I am critical, but am done with cv" cv.signal puts "B: I am still critical, finishing up" } } a.join b.join
В приведенном выше примере выход:
A: I have critical section, but will wait for cv (Later, back at the ranch...) B: Now I am critical, but am done with cv B: I am still critical, finishing up A: I have critical section again! I rule!
Метод класса Thread
Полная нить (нить) метод класса следующим образом:
Нет. | Метод Описание |
---|---|
1 | Thread.abort_on_exception Если это правда, как только поток завершается из-за исключения, весь интерпретатор будет прервана. Значение по умолчанию является ложным, то есть, при нормальных обстоятельствах, если исключение происходит и нить исключение не Thread # присоединиться и другие обнаружены, то поток будет прекращено без предупреждения. |
2 | Thread.abort_on_exception = Если установлено значениеистинно,как только поток завершается из - за исключения, весь интерпретатор будет прервана. Возвращает новое состояние |
3 | Thread.critical Возвращает логическое значение. |
4 | Thread.critical = Если значение верно, то поток не будет включен. Если текущий поток повесить (стоп) или (сигнал) вмешательства, его значение будет автоматически изменено на ложь. |
5 | Thread.current Возвращает текущий выполняемый поток (текущий поток). |
6 | Thread.exit Завершает текущий поток. Возвращает текущий поток. Если текущий поток является единственной нити, используя выход (0), чтобы прекратить его работу. |
7 | Thread.fork {блок} Как и с Thread.new генерировать потоки. |
8 | Thread.kill (AThread) Прервать текущую нить. |
9 | Thread.list Возвращает массив живой работает поток или взвешенном состоянии. |
10 | Thread.main Возврат к главному потоку. |
11 | Thread.new ([аргумент] *) { | агдз | блок} Создавать поток и начать выполнение. Номер будет принят без изменений в блок. Это может запустить поток в то же время, то значение будет передано в локальных переменных, присущих резьбе. |
12 | Thread.pass Право запускать другие темы. Это не изменяет состояние запущенных потоков, но будет передать контроль над другими потоками может работать (Явное планирование потоков). |
13 | Thread.start ([арг] *) { | агдз | блок} Создавать поток и начать выполнение. Номер будет принят без изменений в блок. Это может запустить поток в то же время, то значение будет передано в локальных переменных, присущих резьбе. |
14 | Thread.stop Текущий поток приостанавливается до тех пор, другие потоки запустить метод снова просыпаются нить. |
Метод экземпляра резьбы
В следующем примере вызывается метод экземпляра резьбы присоединения:
#!/usr/bin/ruby thr = Thread.new do # 实例化 puts "In second thread" raise "Raise exception" end thr.join # 调用实例化方法 join
Здесь вы сможете найти полный перечень примеров способа:
Нет. | Метод Описание |
---|---|
1 | Чет [имя] Удалите нить имя, соответствующее присущего данным. Имя может быть строкой или символ. Если имя не соответствует данным, она возвращает ноль. |
2 | Чет [имя] = Установите значение имя потока в соответствующих характеристических данных, имя может быть строка или символ. Если установлено значение ноль, удаляет соответствующие данные в этой теме. |
3 | thr.abort_on_exception Возвращает логическое значение. |
4 | thr.abort_on_exception = Если его значение истинно, то, как только поток завершается из-за исключения, весь интерпретатор будет прервана. |
5 | thr.alive? Если нить "живой", он возвращает истину. |
6 | thr.exit Прервать текущую нить. Возвращает себя. |
7 | thr.join Приостановка текущий поток до тех пор пока сам перспективе, пока поток не завершит свою работу. Если само из-за ненормального завершения работы, текущий поток вызовет такое же исключение. |
8 | thr.key? Если имя, соответствующее присущего данным были определены потоки, а затем возвращает истину |
9 | thr.kill ПодобныйThread.exit. |
10 | thr.priority Возвращает приоритет потока. Приоритет по умолчанию равен 0. Чем больше значение, тем выше приоритет. |
11 | thr.priority = Установка приоритета потока. Вы также можете установить его отрицательным. |
12 | thr.raise (anException) В этой теме насильно выброшены. |
13 | thr.run Перезапуск Pending (стоп) нить. Разница заключается в том, что с пробуждении будет проводить нить сразу переключения. При использовании этого метода, чтобы обрабатывать мертвые воскреснут ThreadError исключение. |
14 | thr.safe_level Возвращает уровень собственной безопасности. Safe_level текущий поток $ SAFE же. |
15 | thr.status Используя строку "Выполнить", "сна" или "ABORTING", чтобы указать статус живой нити, если поток завершается нормально, то он возвращает ложь. Ruoyin аварийное завершение, то он возвращает ноль. |
16 | thr.stop? Если поток прекращается состояние (мертвую) или приостановить (стоп), возвращение истинного. |
17 | thr.value Подождите, пока само поток не прекращается (эквивалент присоединиться), возвращает значение блока нити, если запущенные потоки происходят во время ненормальным, исключение будет поднят снова. |
18 | thr.wakeup Состояние приостанавливается (стоп) нити в состоянии готовности (хода), если метод выполняется на мертвом нить поднимет ThreadError исключение. |