Tutorial Ruby Multithreading Terbaik Pada tahun 2024, Dalam tutorial ini Anda dapat mempelajari Membuat thread Ruby,Siklus benang Hidup,Thread Negara,Benang dan menyimpang,Thread Sinkronisasi,Thread Variabel,Thread prioritas,Thread mutex,jalan buntu,metode kelas Thread,metode contoh benang,
Setiap program yang berjalan pada sistem adalah sebuah proses. Setiap proses berisi satu atau lebih benang.
Sebuah thread adalah aliran kontrol program tunggal berurutan, secara bersamaan menjalankan beberapa thread dalam satu program melakukan hal yang berbeda, yang disebut multi-threading.
Ruby, kita dapat dibuat dengan beberapa kelas thread Thread, Ruby benang adalah ringan, dapat menjadi cara yang efisien untuk menerapkan kode paralel.
Untuk memulai thread baru, Anda hanya dapat memanggil Thread.new:
# 线程 #1 代码部分 Thread.new { # 线程 #2 执行代码 } # 线程 #1 执行代码
Contoh berikut menunjukkan bagaimana menggunakan multithreading dalam program 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}"
Kode di atas dijalankan sebagai akibat dari:
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, membuat thread dapat menggunakan Thread.new, Anda juga dapat menggunakan sintaks Thread.start sama atau Thread.fork tiga cara untuk membuat sebuah thread.
2, membuat sebuah thread tanpa memulai, benang akan dijalankan secara otomatis.
3, kelas Thread mendefinisikan metode untuk memanipulasi benang. Thread blok kode eksekusi Thread.new.
4, blok benang adalah nilai pernyataan terakhir di thread, thread dapat dipanggil oleh metode, jika benang selesai, ia mengembalikan nilai benang, atau tidak mengembalikan nilai sampai thread selesai.
5, metode Thread.current mengembalikan sebuah objek untuk representasi thread saat ini. Metode Thread.main mengembalikan thread utama.
6, metode ini dilakukan oleh benang Thread.Join, metode ini akan menangguhkan thread utama sampai thread saat selesai.
Thread memiliki lima negara:
Thread Negara | Kembali Nilai |
---|---|
executable | menjalankan |
sedang tidur | sedang tidur |
berhenti | batal |
terminasi yang normal | palsu |
terminasi abnormal terjadi | nol |
Ketika pengecualian benang terjadi, dan tidak ada penyelamatan ditangkap, benang biasanya akan dihentikan tanpa peringatan. Namun, jika benang lain Thread # bergabung karena hubungan telah menunggu thread ini, maka benang menunggu juga akan mengangkat pengecualian yang sama.
begin t = Thread.new do Thread.pass # 主线程确实在等join raise "unhandled exception" end t.join rescue p $! # => "unhandled exception" end
Gunakan tiga metode berikut, Anda bisa mendapatkan penerjemah untuk mengganggu operasi ketika thread berakhir karena pengecualian.
Thread.abort_on_exception
mengatur bendera. Thread#abort_on_exception
ditentukan benang set bendera. Bila menggunakan salah satu dari tiga metode yang dijelaskan di atas, seluruh juru akan terganggu.
t = Thread.new { id. } t.abort_on_exception = true
Di Ruby, menyediakan tiga cara disinkronisasi, yaitu:
1. kelas Mutex mengimplementasikan Thread Sinkronisasi
2. Peraturan transfer data Antrian kelas menerapkan sinkronisasi thread
kontrol sinkronisasi 3. Gunakan ConditionVariable
Dengan kelas Mutex mengimplementasikan thread kontrol sinkronisasi, jika Anda juga membutuhkan sebuah program variabel jam di beberapa thread, Anda dapat menggunakan kunci untuk mengunci bagian variabel. Kode adalah sebagai berikut:
#!/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
Kode di atas dijalankan sebagai akibat dari:
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
Selain menggunakan kunci terkunci variabel, Anda juga dapat menggunakan try_lock variabel terkunci, Anda juga dapat menggunakan Mutex.synchronize sinkronisasi akses ke variabel tertentu.
kelas antrian yang merupakan dukungan antrian benang, antrian dapat disinkronkan dengan akhir kunjungan. benang yang berbeda dapat menggunakan kelas terpadu, tapi jangan khawatir tentang apakah data dapat disinkronkan dalam antrian ini, selain untuk membatasi penggunaan SizedQueue panjang antrian kelas
kelas SizedQueue bisa sangat nyaman untuk membantu kami mengembangkan aplikasi berulir untuk menyinkronkan, masalah sinkronisasi harus ditambahkan ke antrian panjang, Anda tidak peduli tentang benang.
produsen klasik dan konsumen:
#!/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
Output Program:
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
Thread dapat memiliki variabel pribadi, benang variabel pribadi benang menulis ketika benang dibuat. Hal ini dapat digunakan dalam lingkup benang, tapi benang tidak dapat dibagi secara eksternal.
Tapi kadang-kadang, variabel lokal benang tidak perlu thread lain atau thread utama untuk mengakses bagaimana melakukan? ruby memungkinkan mereka untuk membuat sebuah thread disediakan oleh nama variabel, benang dipandang sebagai gaya yang serupa tabel hash hash. Berdasarkan [] = ditulis oleh [] membaca data. Kami melihat kode berikut:
#!/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}"
Kode di atas dijalankan output:
8, 0, 3, 7, 2, 1, 6, 5, 4, 9, count = 10
The menunggu thread utama untuk pelaksanaan thread anak selesai, dan kemudian output setiap nilai. .
prioritas thread adalah faktor utama yang mempengaruhi penjadwalan thread. Faktor-faktor lain termasuk lamanya waktu untuk melakukan CPU-benang penjadwalan paket dan sebagainya.
Anda dapat menggunakan Thread.priority diperoleh prioritas thread dan menggunakan Thread.priority = metode untuk menyesuaikan prioritas thread.
default prioritas Sebuah thread untuk 0. eksekusi lebih cepat dari prioritas yang lebih tinggi.
Sebuah Thread dapat mengakses semua data dalam lingkup mereka sendiri, tetapi jika ada benang lain perlu mengakses data di thread harus bagaimana melakukannya? kelas Thread menyediakan data benang mengakses satu sama lain, Anda hanya dapat menempatkan thread sebagai meja Hash, dapat digunakan dalam setiap thread [] data = Write, gunakan [] membaca data.
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"]}" }
Kita bisa melihat, benang sebagai meja Hash, gunakan [] dan [] = metode, kita mencapai berbagi antara benang data.
Mutex (mutal Exclusion = mutex) adalah metode untuk multi-threaded, mekanisme untuk mencegah dua thread secara bersamaan untuk sumber daya yang sama publik (seperti variabel global) membaca dan menulis.
#!/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}"
Jalankan contoh di atas output:
count1 : 9712487 count2 : 12501239 difference : 0
#!/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}"
Jalankan contoh di atas output:
count1 : 1336406 count2 : 1336406 difference : 0
Lebih dari dua unit operasi, kedua belah pihak sedang menunggu yang lain untuk berhenti berjalan, untuk mendapatkan sumber daya sistem, tetapi bukan partai keluar awal, situasi ini disebut kebuntuan.
Misalnya, proses p1 memakan display, sementara Anda harus menggunakan printer, dan printer ditempati oleh p2 proses, p2 juga harus menggunakan monitor, sehingga membentuk kebuntuan.
Ketika kita menggunakan mutex objek membutuhkan perhatian benang kebuntuan.
#!/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 ranchid.)" 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
Contoh di atas output:
A: I have critical section, but will wait for cv (Later, back at the ranchid.) 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 (benang) metode kelas lengkap sebagai berikut:
Tidak. | metode Deskripsi |
---|---|
1 | Thread.abort_on_exception Jika benar, sekali thread berakhir karena pengecualian, seluruh juru akan terganggu. Nilai default adalah palsu, yaitu, dalam keadaan normal, jika pengecualian benang terjadi dan pengecualian tidak Thread # bergabung dan lainnya terdeteksi, benang akan dihentikan tanpa peringatan. |
2 | Thread.abort_on_exception = Jika diatur kebenar,sekali thread berakhir karena pengecualian, seluruh juru akan terganggu. Mengembalikan negara baru |
3 | Thread.critical Mengembalikan nilai Boolean. |
4 | Thread.critical = Ketika nilai benar, benang tidak akan diaktifkan. Jika thread saat untuk menggantung (berhenti) atau sinyal (sinyal) intervensi, nilainya akan secara otomatis berubah ke false. |
5 | Thread.current Mengembalikan thread yang sedang berjalan (thread saat). |
6 | Thread.exit Ini mengakhiri thread saat ini. Mengembalikan thread saat ini. Jika thread saat ini satu-satunya benang, menggunakan pintu keluar (0) untuk mengakhiri operasinya. |
7 | Thread.fork {blok} Seperti dengan Thread.new menghasilkan benang. |
8 | Thread.kill (aThread) Mengakhiri thread berjalan. |
9 | Thread.list Mengembalikan array benang hidup sedang berjalan atau ditangguhkan negara. |
10 | Thread.main Kembali ke thread utama. |
11 | Thread.new ([arg] *) { | args | blok} Menghasilkan benang dan mulai eksekusi. Jumlah tersebut akan diteruskan utuh ke blok. Hal ini dapat memulai thread pada saat yang sama, nilai akan diteruskan ke variabel lokal yang melekat dalam benang. |
12 | Thread.pass hak untuk menjalankan benang lain. Ini tidak mengubah keadaan benang berjalan, tetapi akan menyerahkan kontrol dari benang lainnya dapat berjalan (Explicit penjadwalan thread). |
13 | Thread.start ([args] *) { | args | blok} Menghasilkan benang dan mulai eksekusi. Jumlah tersebut akan diteruskan utuh ke blok. Hal ini dapat memulai thread pada saat yang sama, nilai akan diteruskan ke variabel lokal yang melekat dalam benang. |
14 | Thread.stop Thread saat ditangguhkan sampai benang lain metode berlari lagi bangun benang. |
Contoh berikut memanggil metode benang contoh bergabung:
#!/usr/bin/ruby thr = Thread.new do # 实例化 puts "In second thread" raise "Raise exception" end thr.join # 调用实例化方法 join
Berikut adalah daftar lengkap contoh metode:
Tidak. | metode Deskripsi |
---|---|
1 | thr [nama] Lepaskan benang nama sesuai dengan data yang melekat. Nama bisa berupa string atau simbol. Jika nama tidak sesuai dengan data, ia mengembalikan nil. |
2 | thr [nama] = Mengatur nilai nama benang dalam data karakteristik yang sesuai, nama bisa berupa string atau simbol. Jika nil, menghapus data yang sesuai di thread ini. |
3 | thr.abort_on_exception Mengembalikan nilai Boolean. |
4 | thr.abort_on_exception = Jika nilainya benar, maka sekali thread berakhir karena pengecualian, seluruh juru akan terganggu. |
5 | thr.alive? Jika benang adalah "hidup", ia mengembalikan benar. |
6 | thr.exit Mengakhiri thread berjalan. Pengembalian diri. |
7 | thr.join Menunda thread saat sampai diri berjalan sampai benang berakhir. Jika diri karena terminasi abnormal, benang saat ini akan memicu pengecualian yang sama. |
8 | thr.key? Jika nama yang sesuai dengan data yang melekat telah benang didefinisikan, kemudian kembali benar |
9 | thr.kill Thread.exit serupa. |
10 | thr.priority Mengembalikan prioritas thread. Prioritas default adalah 0. besar nilai, semakin tinggi prioritas. |
11 | thr.priority = Mengatur prioritas thread. Anda juga dapat mengaturnya untuk negatif. |
12 | thr.raise (anException) Dalam thread ini paksa dilemparkan. |
13 | thr.run Restart Tertunda (berhenti) thread. Perbedaannya adalah bahwa dengan wakeup akan melakukan benang beralih segera. Jika menggunakan metode ini untuk memproses orang mati akan dibangkitkan ThreadError pengecualian. |
14 | thr.safe_level Mengembalikan tingkat keamanan diri. Safe_level benang saat ini $ SAFE yang sama. |
15 | thr.status Menggunakan string "run", "tidur" atau "batal" untuk menunjukkan status dari benang hidup jika thread dihentikan normal, maka kembali palsu. Ruoyin normal terminasi, maka kembali nihil. |
16 | thr.stop? Jika benang diakhiri negara (mati) atau menangguhkan (berhenti), kembali benar. |
17 | thr.value Tunggu sampai thread diri berakhir (setara dengan bergabung), kembali nilai dari blok benang jika benang berjalan terjadi selama normal, pengecualian akan dibangkitkan lagi. |
18 | thr.wakeup Negara ditangguhkan (stop) dari benang ke siap negara (run), jika metode ini dilakukan pada thread mati akan menaikkan pengecualian ThreadError. |