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.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. الطبقة المزامنة تنفذ التزامن الموضوع

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

اكتمال ينتظر موضوع الرئيسية لتنفيذ موضوع الطفل، ومن ثم إخراج كل قيمة. .


الأولوية الموضوع

الأولوية الموضوع هو العامل الرئيسي الذي يؤثر على جدولة موضوع. وتشمل العوامل الأخرى طول الفترة الزمنية لأداء وحدة المعالجة المركزية موضوع جدولة حزم وهلم جرا.

يمكنك استخدام 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 = مزامنة) هي طريقة لمتعددة الخيوط البرمجة، آلية لمنع اثنين من المواضيع في وقت واحد على نفس الموارد العامة (مثل المتغيرات العالمية) القراءة والكتابة.

أمثلة على عدم استخدام 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!

أسلوب فئة الموضوع

كامل الموضوع (موضوع) أسلوب فئة على النحو التالي:

لا. طريقة الوصف
1 Thread.abort_on_exception
وإذا كان صحيحا، مرة واحدة إنهاء الموضوع بسبب استثناء، سيتم مقاطعة مترجم كامل. القيمة الافتراضية هي كاذبة، وهذا هو، في ظل الظروف العادية، في حالة حدوث استثناء موضوع والاستثناء ليس الموضوع # انضمام وغيرها من الكشف، سيتم إنهاء موضوع دون سابق إنذار.
2 Thread.abort_on_exception =
إذا تم تعيين إلىصحيح،مرة واحدة إنهاء الموضوع بسبب استثناء، سيتم مقاطعة مترجم كامل. يعود الدولة الجديدة
3 Thread.critical
إرجاع قيمة منطقية.
4 Thread.critical =
عندما تكون القيمة الحقيقية، لن يتم تبديل الموضوع. إذا كان الترابط الحالي لتعليق (توقف) أو إشارة (إشارة) تدخل، وسيتم تغيير قيمته تلقائيا إلى false.
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] *) { | وسائط | كتلة}
توليد موضوع والبدء في التنفيذ. سيتم تمرير عدد سليمة إلى كتلة، وهذا يمكن البدء في نشر موضوع في نفس الوقت، سيتم تمرير القيمة إلى المتغيرات المحلية المتأصلة في الموضوع.
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
إعادة قيد الانتظار (توقف) موضوع، والفرق هو أنه مع التنبيه ستجري موضوع التحول فورا. إذا كنت تستخدم هذه الطريقة لمعالجة سيتم رفع القتلى استثناء ThreadError.
14 thr.safe_level
يعود مستوى الأمن الذاتي. Safe_level في موضوع $ الحالي SAFE نفسه.
15 thr.status
باستخدام سلسلة "المدى"، "النوم" أو "اجهاض" للإشارة إلى حالة من موضوع العيش إذا تم إنهاء الموضوع بشكل عادي، ثم فإنها ترجع كاذبة. Ruoyin لإنهاء غير طبيعي، ثم يعود لا شيء.
16 thr.stop؟
إذا تم إنهاء موضوع الدولة (ميتا) أو تعليق (توقف)، والعودة الحقيقية.
17 thr.value
انتظر حتى إنهاء موضوع الذاتي (أي ما يعادل الانضمام)، إرجاع قيمة كتلة من موضوع إذا كانت المواضيع تشغيل تحدث أثناء غير طبيعي، سيتم رفع الاستثناء مرة أخرى.
18 thr.wakeup
وعلقت الدولة (وقف) من موضوع إلى الدولة جاهزة (المدى)، إذا يتم تنفيذ الأسلوب على موضوع ميت سترفع ThreadError استثناء.