Latest web development tutorials

루비 멀티 스레딩

시스템에서 실행하는 각 프로그램 공정이다. 각 프로세스는 하나 이상의 스레드가 포함되어 있습니다.

스레드가 동시에 하나의 프로그램에서 여러 스레드가 멀티 스레딩라는 다른 일을 수행 실행, 하나의 순차 프로그램 제어 흐름입니다.

루비, 우리는 다수의 스레드를 스레드 클래스가 생성 될 수 루비 스레드는 병렬 코드를 구현하기위한 효율적인 방법이 될 수 있고, 경량이다.


루비 스레드를 생성

새 스레드를 시작하려면, 당신은 단지 Thread.new를 호출 할 수 있습니다 :

# 线程 #1 代码部分
Thread.new {
  # 线程 #2 执行代码
}
# 线程 #1 执行代码

다음의 예는 루비 프로그램에서 멀티 스레딩을 사용하는 방법을 보여줍니다 :

#!/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 클래스는 스레드를 조작하는 방법을 정의합니다. 실행 Thread.new 코드 블록의 스레드.

도 4는 나사 블록은 스레드의 값을 리턴하거나, 스레드가 종료 될 때까지 값을 반환하지 않는 스레드가 완료되면 스레드의 마지막 문장의 값은 스레드가 메소드에 의해 호출 될 수있다.

5 Thread.current 방법은 현재의 thread의 표현 개체를 반환합니다. Thread.main 방법은 주 스레드를 반환합니다.

(6), 메소드가 Thread.join를 스레드에 의해 수행되고, 주 스레드를 일시 중단이 메소드는 현재 스레드가 끝날 때까지.


스레드 상태

스레드는 다섯 가지 상태가 있습니다 :

스레드 상태 반환 값
실행 달리기
종료 중단
정상 종료 그릇된
비정상 종료가 발생합니다

스레드와 탈선

스레드 예외가 발생하고, 어떤 구조가 포착되지 않은 경우, 스레드는 일반적으로 경고없이 종료된다. 관계가이 스레드를 기다리고 있기 때문에 다른 스레드 스레드 # 가입하는 경우에는 다음 대기중인 스레드도 같은 예외가 발생합니다.

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 지정된 thread 세트 플래그.

위에서 설명한 3 가지 방법을 사용하면 전체 통역자가 중단 될 것이다.

t = Thread.new { ... }
t.abort_on_exception = true

스레드 동기화

루비에서, 즉, 세 개의 동기화 된 방식을 제공합니다 :

1. 뮤텍스 클래스는 스레드 동기화를 구현

2. 규정 데이터 전송 큐 클래스 스레드 동기화를 구현

3. ConditionVariable 동기화 제어

뮤텍스으로 클래스는 스레드 동기화를 구현

당신은 또한 다중 스레드 프로그램 변수 시계를 필요로하는 경우 뮤텍스 클래스, 스레드 동기 제어를 구현, 당신은 변수 부분을 잠그는 잠금을 사용할 수 있습니다. 다음과 같이 코드입니다 :

#!/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 특정 변수에 대한 액세스를 동기화 할 수 있습니다.

큐 클래스 규제 데이터 전송 스레드 동기화를 구현

스레드지지 큐를 나타내는 큐 클래스 큐는 매장의 단부에 동기화 될 수있다. 다른 스레드 클래스 통합을 사용할 수 있지만 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

자식 스레드가 실행을 위해 메인 쓰레드 대기 완료하고 각각의 값을 출력한다. .


스레드 우선 순위

스레드의 우선 순위 스레드 스케줄링에 영향을 미치는 주요 요인이다. 다른 요인 등 CPU 스레드 패킷 스케줄링을 수행하는 시간을 포함한다.

당신은 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"]}" }

우리는 []를 사용, 해시 테이블과 스레드를 볼 수 있고 [] = 방법, 우리는 스레드간에 데이터 공유를 달성했다.


스레드 뮤텍스

뮤텍스 (Mutal 탈락 = 뮤텍스) 멀티 스레드 프로그래밍하는 방법이다 (이러한 전역 변수)을 동일한 공용 자원을 동시에 2 스레드를 방지하기위한기구를 읽고 쓸.

비 사용 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)이 디스플레이를 취하고, 프린터가 처리 (P2)에 의해 점유되고, P2는 따라서 교착 형성 모니터를 사용한다.

우리가 뮤텍스를 사용하면 개체주의 스레드 교착 상태를 필요로한다.

#!/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
스레드가 종료되면 그것 때문에 예외에 해당하는 경우, 전체 통역이 중단됩니다. 기본값은 스레드 예외가 발생하고 예외 # 가입 검출 다른 스레드가 경고없이 종료됩니다 스레드되지 않은 경우 즉, 정상적인 상황에서,이다, false입니다.
Thread.abort_on_exception =
true로설정하면 예외로, 전체 통역이 중단 될 것입니다때문에,한 번 스레드가 종료됩니다. 새로운 상태를 돌려줍니다
3 Thread.critical
부울 값을 반환합니다.
4 Thread.critical =
값에 해당하는 경우, 스레드는 전환되지 않을 것이다. 현재의 thread가 (정지) 또는 신호 (신호)의 개입이 중단 된 경우, 그 값은 자동으로 false로 변경됩니다.
(5) Thread.current
현재 실행중인 스레드 (현재의 thread)를 돌려줍니다.
6 Thread.exit
그것은 현재의 thread를 종료합니다. 현재의 thread를 돌려줍니다. 현재의 thread가 출구를 사용하는 유일한 스레드 (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) THR [이름]
고유 데이터에 대응하는 이름의 실을 제거한다. 이름은 문자열이나 기호를 할 수 있습니다. 이름 데이터에 대응하지 않는 경우, 무를 반환한다.
THR [이름] =
해당 특성 데이터의 스레드 이름 값을 설정, 이름은 문자열이나 기호를 할 수 있습니다. 전무로 설정하면,이 글의 해당 데이터를 제거합니다.
3 thr.abort_on_exception
부울 값을 반환합니다.
4 thr.abort_on_exception =
그 값에 해당하는 경우는 예외로, 전체 통역 서비스가 중단됩니다 인해, 다음 스레드가 종료되면.
(5) thr.alive?
스레드가 "라이브"인 경우, true를 돌려줍니다.
6 thr.exit
스레드 실행을 종료합니다. 자기를 돌려줍니다.
(7) thr.join
스레드가 종료 될 때까지 자동 실행 될 때까지 현재 스레드를 일시 중단합니다. 비정상 종료로 인해 자기, 현재의 thread가 같은 예외가 트리거됩니다.
8 thr.key?
고유 데이터에 대응하는 이름으로 정의 스레드 되었다면, true를 반환
9 thr.kill
유사Thread.exit.
(10) thr.priority
스레드의 우선 순위를 반환합니다. 기본 우선 순위는 우선 순위가 높은, 값이 클수록 0입니다.
(11) thr.priority =
스레드 우선 순위를 설정. 또한 음으로 설정할 수 있습니다.
(12) thr.raise (anException)
이 스레드 내에서 강제적으로 발생합니다.
(13) thr.run
보류 (정지) 스레드를 다시 시작합니다. 차이가 절전 모드로 스레드 즉시 전환을 수행 할 것입니다.이 방법을 사용하면 죽은 ThreadError 예외가 발생합니다 처리하는 경우.
(14) thr.safe_level
자체 보안 수준을 돌려줍니다. 같은 현재의 thread $으로 SAFE Safe_level.
(15) thr.status
스레드가 정상적으로 종료되면 문자열 "실행", "수면"또는 "중단"을 사용하면 다음 false를 반환, 라이브 스레드의 상태를 나타냅니다. Ruoyin 비정상 종료를, 다음이 전무를 반환합니다.
(16) thr.stop?
스레드 상태 (죽은), 종료 (정지)가 true를 반환 일시 중단됩니다.
(17) thr.value
자기 스레드 (가입 당량)를 종료 할 때까지 실행하는 스레드가 비정상 중에 예외가 다시 발생한다 발생할 경우, 스레드의 블록의 값을 반환 기다린다.
(18) thr.wakeup
이 방법은 ThreadError 예외를 발생합니다 죽은 스레드에서 수행되는 경우 상태는 준비 상태 (실행)에 스레드 (정지) 일시 중단됩니다.