루비 멀티 스레딩
시스템에서 실행하는 각 프로그램 공정이다. 각 프로세스는 하나 이상의 스레드가 포함되어 있습니다.
스레드가 동시에 하나의 프로그램에서 여러 스레드가 멀티 스레딩라는 다른 일을 수행 실행, 하나의 순차 프로그램 제어 흐름입니다.
루비, 우리는 다수의 스레드를 스레드 클래스가 생성 될 수 루비 스레드는 병렬 코드를 구현하기위한 효율적인 방법이 될 수 있고, 경량이다.
루비 스레드를 생성
새 스레드를 시작하려면, 당신은 단지 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 예외를 발생합니다 죽은 스레드에서 수행되는 경우 상태는 준비 상태 (실행)에 스레드 (정지) 일시 중단됩니다. |