Latest web development tutorials
×

Ruby หลักสูตร

Ruby หลักสูตร Ruby แนะนำโดยย่อ Ruby สิ่งแวดล้อม Ruby ติดตั้ง Linux Ruby ติดตั้ง Windows Ruby การเข้ารหัสจีน Ruby เลือกบรรทัดคำสั่ง Ruby ตัวแปรสภาพแวดล้อม Ruby ไวยากรณ์ Ruby ชนิดข้อมูล Ruby คลาสและวัตถุ Ruby กรณีระดับ Ruby ตัวแปร Ruby ผู้ประกอบการ Ruby หมายเหตุ Ruby เงื่อนไข Ruby การไหลเวียน Ruby ทาง Ruby กลุ่ม Ruby โมดูล Ruby เชือก Ruby แถว Ruby กัญชา Ruby วันที่และเวลา Ruby ขอบเขต Ruby iterator Ruby input และ output ไฟล์ Ruby File ชั้นเรียนและวิธี Ruby Dir ชั้นเรียนและวิธี Ruby ผิดปกติ

Ruby การสอนที่ทันสมัย

Ruby เชิงวัตถุ Ruby นิพจน์ปกติ Ruby การเข้าถึงฐานข้อมูล - DBI หลักสูตร Ruby MySQL Ruby CGI โครงการ Ruby CGI ทาง Ruby CGI Cookies Ruby CGI Sessions Ruby ส่ง Email SMTP Ruby Socket โครงการ Ruby XML, XSLT, XPath Ruby Web Services Ruby multithreading Ruby JSON Ruby RubyGems

ทับทิม Multithreading

โปรแกรมที่ทำงานบนระบบแต่ละกระบวนการ แต่ละขั้นตอนมีมากกว่าหนึ่งหัวข้อ

ด้ายเป็นโปรแกรมควบคุมการไหลลำดับเดียวทำงานพร้อมกันหลายกระทู้ในโปรแกรมเดียวทำสิ่งที่แตกต่างกันเรียกว่ามัลติเธรด

ทับทิมเราสามารถสร้างขึ้นโดยหลายชั้นหัวข้อกระทู้หัวข้อทับทิมมีน้ำหนักเบาก็สามารถจะเป็นวิธีที่มีประสิทธิภาพในการใช้รหัสขนาน


สร้างหัวข้อทับทิม

ในการเริ่มต้นหัวข้อใหม่คุณก็สามารถโทร 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.new บล็อกรหัส

4 บล็อกด้ายคือค่าของคำสั่งสุดท้ายในด้าย, ด้ายที่สามารถเรียกใช้โดยวิธีการที่ถ้าด้ายเสร็จแล้วก็ส่งกลับค่าของด้ายหรือไม่คืนค่าจนด้ายเสร็จสิ้น

5 วิธี Thread.current ส่งกลับวัตถุสำหรับการเป็นตัวแทนเธรดปัจจุบัน วิธี 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 ด้ายระบุธงชุด

เมื่อใช้หนึ่งในสามวิธีที่อธิบายข้างต้นล่ามทั้งหมดจะถูกขัดจังหวะ

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

ประสานด้าย

ในทับทิมยังมีลักษณะที่ตรงกันสามคือ:

1. ระดับ Mutex ดำเนินการประสานด้าย

2. การถ่ายโอนข้อมูลระดับคิวกำกับดูแลการดำเนินการประสานด้าย

การควบคุมการประสาน 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 ประสานการเข้าถึงตัวแปรโดยเฉพาะอย่างยิ่ง

การถ่ายโอนข้อมูลการกำกับดูแลของการเรียนคิวดำเนินประสานด้าย

ระดับที่แสดงถึงคิวคิวสนับสนุนด้ายคิวสามารถตรงไปยังจุดสิ้นสุดของการเข้าชม หัวข้อที่แตกต่างกันสามารถใช้การเรียนแบบครบวงจร แต่ไม่ต้องกังวลเกี่ยวกับว่าข้อมูลที่สามารถทำข้อมูลให้ตรงกันในคิวนี้นอกเหนือไปจากการ จำกัด การใช้ 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"]}" }

เราสามารถมองเห็นด้ายเป็นตารางแฮชใช้ [] และ [] = วิธีเราประสบความสำเร็จการแบ่งปันข้อมูลระหว่างหัวข้อ


mutex กระทู้

mutex (ยกเว้น Mutal = 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 กระบวนการจะขึ้นแสดงในขณะที่คุณต้องใช้เครื่องพิมพ์และเครื่องพิมพ์ที่ถูกครอบครองโดย P2 กระบวนการ P2 ยังต้องใช้จอแสดงผลจึงเกิดการหยุดชะงัก

เมื่อเราใช้ Mutex วัตถุต้องการหยุดชะงักด้ายความสนใจ

ตัวอย่าง

#!/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!

วิธีการเรียนของกระทู้

กระทู้ (ด้าย) วิธีการเรียนที่สมบูรณ์ดังนี้

เลขที่ วิธีการรายละเอียด
1 Thread.abort_on_exception
ถ้ามันเป็นความจริงเมื่อด้ายยุติเนื่องจากการยกเว้น, ล่ามทั้งหมดจะถูกขัดจังหวะ ค่าเริ่มต้นเป็นเท็จ, ที่อยู่ภายใต้สถานการณ์ปกติถ้ายกเว้นด้ายเกิดขึ้นและข้อยกเว้นไม่ด้าย # เข้าร่วมและตรวจพบอื่น ๆ ด้ายจะถูกยกเลิกโดยไม่มีการเตือน
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 ([ARG] *) { | args | บล็อก}
สร้างด้ายและเริ่มต้นการดำเนินการ จำนวนจะถูกส่งผ่านไปเหมือนเดิมเพื่อป้องกัน. นี้สามารถเริ่มต้นด้ายในเวลาเดียวกันค่าจะถูกส่งผ่านไปตัวแปรท้องถิ่นที่มีอยู่ในหัวข้อ
12 Thread.pass
สิทธิในการเรียกใช้หัวข้ออื่น ๆ . มันไม่ได้เปลี่ยนสถานะของหัวข้อการทำงาน แต่จะมือเหนือการควบคุมของหัวข้ออื่น ๆ สามารถเรียกใช้ (การตั้งเวลาด้าย Explicit)
13 thread.start (args [] *) { | args | บล็อก}
สร้างด้ายและเริ่มต้นการดำเนินการ จำนวนจะถูกส่งผ่านไปเหมือนเดิมเพื่อป้องกัน. นี้สามารถเริ่มต้นด้ายในเวลาเดียวกันค่าจะถูกส่งผ่านไปตัวแปรท้องถิ่นที่มีอยู่ในหัวข้อ
14 Thread.stop
เธรดปัจจุบันถูกระงับจนกว่าหัวข้ออื่น ๆ วิธีการทำงานอีกครั้งตื่นขึ้นมาด้าย

วิธีการเช่นด้าย

ตัวอย่างต่อไปนี้เรียกวิธีการเช่นด้ายเข้าร่วม:

#!/usr/bin/ruby

thr = Thread.new do   # 实例化
   puts "In second thread"
   raise "Raise exception"
end
thr.join   # 调用实例化方法 join

นี่คือรายการที่สมบูรณ์ของตัวอย่างของวิธีการ:

เลขที่ วิธีการรายละเอียด
1 THR [ชื่อ]
นำด้ายชื่อที่สอดคล้องกับข้อมูลที่โดยธรรมชาติ ชื่ออาจจะเป็นสตริงหรือสัญลักษณ์ ถ้าชื่อไม่ตรงกับข้อมูลที่จะส่งกลับศูนย์
2 THR [ชื่อ] =
ตั้งค่าชื่อด้ายในข้อมูลลักษณะที่สอดคล้องกันชื่ออาจจะเป็นสตริงหรือสัญลักษณ์ ถ้าตั้งค่าเป็นศูนย์เอาข้อมูลที่สอดคล้องกันในหัวข้อนี้
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
รีสตาร์ทเครื่องรอดำเนินการ (หยุด) ด้าย. แตกต่างคือมี Wakeup จะดำเนินการเปลี่ยนด้ายทันที. ถ้าใช้วิธีนี้ในการประมวลผลที่ตายไปแล้วจะได้รับการเลี้ยงดูยกเว้น ThreadError
14 thr.safe_level
ผลตอบแทนที่ระดับความปลอดภัยของตัวเอง. Safe_level ด้าย $ ปัจจุบัน SAFE เดียวกัน
15 thr.status
ใช้สตริง "Run", "นอนหลับ" หรือ "ยกเลิก" เพื่อแสดงสถานะของด้ายสดถ้าด้ายยกเลิกโดยปกติแล้วมันกลับเท็จ. Ruoyin ยกเลิกความผิดปกติแล้วก็จะส่งกลับศูนย์
16 thr.stop?
ถ้าด้ายถูกยกเลิกรัฐ (ตาย) หรือระงับ (หยุด) ผลตอบแทนที่แท้จริง
17 thr.value
รอจนด้ายตนเองยุติ (เทียบเท่าเข้าร่วม) ส่งกลับค่าของบล็อกของด้ายถ้าหัวข้อการทำงานเกิดขึ้นในช่วงที่ผิดปกติยกเว้นจะเพิ่มขึ้นอีกครั้ง
18 thr.wakeup
รัฐถูกระงับ (STOP) ของด้ายไปที่สถานะ Ready (Run) ถ้าวิธีการที่จะดำเนินการในหัวข้อตายจะเพิ่มข้อยกเว้น ThreadError