Python berbilang benang
Berbilang benang adalah serupa dengan melaksanakan berbilang program berbeza pada masa yang sama mempunyai kelebihan berikut:
Menggunakan benang boleh meletakkan tugas dalam jangka panjang. program ke Diproses di latar belakang.
Antara muka pengguna boleh menjadi lebih menarik, jadi jika pengguna mengklik butang untuk mencetuskan pemprosesan acara tertentu, bar kemajuan boleh muncul untuk menunjukkan kemajuan pemprosesan
Kelajuan berjalan program mungkin dipercepatkan
Benang lebih berguna dalam melaksanakan beberapa tugas menunggu seperti input pengguna, membaca fail dan menulis , dan rangkaian menghantar dan menerima data, dsb. Dalam kes ini kita boleh mengeluarkan beberapa sumber berharga seperti penggunaan memori dan sebagainya.
Benang masih berbeza daripada proses semasa pelaksanaan. Setiap urutan bebas mempunyai titik masuk untuk pelaksanaan program, urutan pelaksanaan berurutan dan titik keluar untuk program. Walau bagaimanapun, benang tidak boleh dilaksanakan secara bebas dan mesti wujud dalam program aplikasi, dan program aplikasi menyediakan kawalan pelaksanaan berbilang benang.
Setiap utas mempunyai set daftar CPU sendiri, dipanggil konteks utas, yang mencerminkan keadaan daftar CPU kali terakhir utas dijalankan.
Penuding arahan dan daftar penuding tindanan ialah dua daftar paling penting dalam konteks utas Alamat ini digunakan untuk menandakan memori dalam ruang alamat proses yang dimiliki benang itu.
Benang boleh didahulukan (terganggu).
Benang boleh ditunda (juga dipanggil tidur) semasa utas lain berjalan -- ini dipanggil pengunduran benang.
Mula belajar benang Python
Terdapat dua cara untuk menggunakan benang dalam Python: fungsi atau kelas untuk membungkus objek benang.
Fungsi: Panggil fungsi start_new_thread() dalam modul benang untuk menjana urutan baharu. Sintaksnya adalah seperti berikut:
thread.start_new_thread ( function, args[, kwargs] )
Perihalan parameter:
fungsi - fungsi benang.
args - parameter yang dihantar ke fungsi benang, ia mestilah jenis tupel.
kwarg - parameter pilihan.
Contoh:
#!/usr/bin/python # -*- coding: UTF-8 -*- import thread import time # 为线程定义一个函数 def print_time( threadName, delay): count = 0 while count < 5: time.sleep(delay) count += 1 print "%s: %s" % ( threadName, time.ctime(time.time()) ) # 创建两个线程 try: thread.start_new_thread( print_time, ("Thread-1", 2, ) ) thread.start_new_thread( print_time, ("Thread-2", 4, ) ) except: print "Error: unable to start thread" while 1: pass
Hasil keluaran melaksanakan program di atas adalah seperti berikut:
Thread-1: Thu Jan 22 15:42:17 2009 Thread-1: Thu Jan 22 15:42:19 2009 Thread-2: Thu Jan 22 15:42:19 2009 Thread-1: Thu Jan 22 15:42:21 2009 Thread-2: Thu Jan 22 15:42:23 2009 Thread-1: Thu Jan 22 15:42:23 2009 Thread-1: Thu Jan 22 15:42:25 2009 Thread-2: Thu Jan 22 15:42:27 2009 Thread-2: Thu Jan 22 15:42:31 2009 Thread-2: Thu Jan 22 15:42:35 2009
Penghujung benang biasanya bergantung pada semula jadi penghujung fungsi utas; ia juga boleh dilakukan dalam utas Apabila thread.exit() dipanggil dalam fungsi, ia membuang pengecualian SystemExit untuk keluar dari utas.
Modul threading
Python menyediakan sokongan untuk thread melalui dua perpustakaan standard, thread dan threading. benang menyediakan benang peringkat rendah, primitif dan kunci mudah.
Kaedah lain yang disediakan oleh modul thread:
threading.currentThread(): Mengembalikan pembolehubah thread semasa.
threading.enumerate(): Mengembalikan senarai yang mengandungi benang yang sedang berjalan. Running merujuk kepada thread selepas ia bermula dan sebelum ia tamat, tidak termasuk thread sebelum permulaan dan selepas penamatan.
threading.activeCount(): Mengembalikan bilangan thread yang sedang berjalan, yang mempunyai hasil yang sama seperti len(threading.enumerate()).
Selain kaedah penggunaan, modul thread juga menyediakan kelas Thread untuk mengendalikan thread. Kelas Thread menyediakan kaedah berikut:
run() : Kaedah yang digunakan untuk mewakili aktiviti benang.
start():Mulakan aktiviti thread.
sertai([masa]): Tunggu sehingga urutan tamat. Ini menyekat utas panggilan sehingga kaedah join() utas dipanggil batalkan - keluar seperti biasa atau buang pengecualian yang tidak dikendalikan - atau tamat masa pilihan berlaku.
isAlive(): Mengembalikan sama ada urutan itu aktif.
getName(): Mengembalikan nama urutan.
setName(): Tetapkan nama benang.
Gunakan modul Threading untuk mencipta thread
Gunakan modul Threading untuk mencipta thread, warisi terus daripada threading.Thread, dan kemudian ganti __init__ kaedah dan kaedah jalankan:
#!/usr/bin/python # -*- coding: UTF-8 -*- import threading import time exitFlag = 0 class myThread (threading.Thread): #继承父类threading.Thread def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): #把要执行的代码写到run函数里面 线程在创建后会直接运行run函数 print "Starting " + self.name print_time(self.name, self.counter, 5) print "Exiting " + self.name def print_time(threadName, delay, counter): while counter: if exitFlag: thread.exit() time.sleep(delay) print "%s: %s" % (threadName, time.ctime(time.time())) counter -= 1 # 创建新线程 thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # 开启线程 thread1.start() thread2.start() print "Exiting Main Thread"
Hasil pelaksanaan program di atas adalah seperti berikut; mungkin berlaku untuk memastikan ketepatan data, berbilang benang perlu disegerakkan.
Penyegerakan benang mudah boleh dicapai menggunakan Kunci objek Benang dan Rlock Kedua-dua objek mempunyai kaedah perolehan dan pelepasan Untuk data yang memerlukan hanya satu utas untuk beroperasi pada satu-satu masa, operasinya boleh diletakkan di antara perolehan dan pelepasan kaedah. Seperti berikut: Kelebihan multi-threading ialah ia boleh menjalankan pelbagai tugas pada masa yang sama (sekurang-kurangnya begitulah rasanya). Tetapi apabila urutan perlu berkongsi data, mungkin terdapat masalah data di luar penyegerakan. Pertimbangkan situasi ini: semua elemen dalam senarai adalah 0, benang "set" menukar semua elemen kepada 1 dari belakang ke hadapan, dan benang "cetak" bertanggungjawab untuk membaca senarai dari depan ke belakang dan percetakan . Kemudian, mungkin apabila benang "ditetapkan" mula berubah, benang "cetak" akan mencetak senarai, dan output akan menjadi separuh 0 dan separuh 1. Ini adalah penyahsegerakan data. Untuk mengelakkan situasi ini, konsep kunci diperkenalkan. Kunci mempunyai dua keadaan - terkunci dan tidak berkunci. Apabila utas seperti "set" ingin mengakses data yang dikongsi, ia mesti mendapatkan kunci terlebih dahulu jika utas lain seperti "cetak" telah memperoleh kunci, kemudian biarkan utas "set" dijeda, iaitu penyekatan segerak; sehingga benang " Cetak "Selepas akses selesai dan kunci dilepaskan, biarkan benang "ditetapkan" diteruskan. Selepas pemprosesan sedemikian, apabila mencetak senarai, sama ada semua 0 atau semua 1 akan dikeluarkan, dan tidak akan ada lagi adegan memalukan separuh 0 dan separuh 1. Contoh:
Starting Thread-1 Starting Thread-2 Exiting Main Thread Thread-1: Thu Mar 21 09:10:03 2013 Thread-1: Thu Mar 21 09:10:04 2013 Thread-2: Thu Mar 21 09:10:04 2013 Thread-1: Thu Mar 21 09:10:05 2013 Thread-1: Thu Mar 21 09:10:06 2013 Thread-2: Thu Mar 21 09:10:06 2013 Thread-1: Thu Mar 21 09:10:07 2013 Exiting Thread-1 Thread-2: Thu Mar 21 09:10:08 2013 Thread-2: Thu Mar 21 09:10:10 2013 Thread-2: Thu Mar 21 09:10:12 2013 Exiting Thread-2
Baris Gilir Keutamaan Benang (Baris Gilir)
Modul Baris Gilir Python menyediakan kelas gilir selamat benang yang segerak, termasuk FIFO (Masuk dahulu keluar) baris gilir, baris gilir LIFO (terakhir masuk dahulu) baris gilir LifoQueue, dan baris gilir keutamaan PriorityQueue. Barisan gilir ini melaksanakan kunci primitif dan boleh digunakan terus dalam berbilang benang. Baris gilir boleh digunakan untuk mencapai penyegerakan antara utas.
Kaedah biasa dalam modul Baris:
Queue.qsize() mengembalikan saiz baris gilir
Queue.empty() Jika baris gilir kosong, mengembalikan True, sebaliknya False
Barisan penuh() Jika baris gilir penuh, kembalikan Benar, jika tidak Salah
Barisan penuh sepadan dengan saiz saiz maksimum
-
Queue.get([blok[, tamat masa]]) mendapat giliran, masa menunggu tamat masa
Queue.get_nowait() bersamaan dengan Queue.get (Salah)
Queue.put(item) menulis pada baris gilir, masa menunggu tamat masa
Queue.put_nowait(item) adalah bersamaan dengan Queue.put(item, False)
Queue.task_done() Selepas menyelesaikan tugas, fungsi Queue.task_done() menghantar isyarat kepada baris gilir di mana tugas telah selesai < . hasil pelaksanaan program di atas:
#!/usr/bin/python # -*- coding: UTF-8 -*- import threading import time class myThread (threading.Thread): def __init__(self, threadID, name, counter): threading.Thread.__init__(self) self.threadID = threadID self.name = name self.counter = counter def run(self): print "Starting " + self.name # 获得锁,成功获得锁定后返回True # 可选的timeout参数不填时将一直阻塞直到获得锁定 # 否则超时后将返回False threadLock.acquire() print_time(self.name, self.counter, 3) # 释放锁 threadLock.release() def print_time(threadName, delay, counter): while counter: time.sleep(delay) print "%s: %s" % (threadName, time.ctime(time.time())) counter -= 1 threadLock = threading.Lock() threads = [] # 创建新线程 thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # 开启新线程 thread1.start() thread2.start() # 添加线程到线程列表 threads.append(thread1) threads.append(thread2) # 等待所有线程完成 for t in threads: t.join() print "Exiting Main Thread"