Latest web development tutorials

Python3 Multithreading

Beberapa thread secara bersamaan dijalankan mirip dengan sejumlah program yang berbeda, operasi multithreaded memiliki keuntungan sebagai berikut:

  • Menggunakan benang dapat menempati Program panjang dalam tugas ke latar belakang untuk menangani.
  • Antarmuka pengguna mungkin lebih menarik, jadi misalnya pengguna mengklik tombol untuk memicu beberapa peristiwa penanganan, Anda dapat pop progress bar untuk menunjukkan kemajuan proses
  • Kecepatan lari bisa mempercepat
  • Pada menyadari beberapa tugas, seperti menunggu input pengguna, melek dokumen dan jaringan untuk mengirim dan menerima data, benang lebih berguna. Dalam hal ini, kita dapat membebaskan beberapa sumber daya berharga, seperti penggunaan memori dan sebagainya.

Benang dalam proses implementasi dan proses yang berbeda. Masing-masing memiliki thread terpisah berjalan masuk, urutan keluar dan prosedur pelaksanaan perintah. Tapi thread ini tidak mampu melakukan secara mandiri, itu harus ada sesuai dengan aplikasi, memberikan beberapa benang eksekusi dikendalikan oleh aplikasi.

Setiap thread memiliki set sendiri dari register CPU, yang disebut konteks benang, konteks benang mencerminkan menjalankan terakhir dari negara benang CPU mendaftar.

Instruksi pointer dan stack pointer register adalah dua register konteks thread yang paling penting, benang selalu akan berjalan dalam konteks proses, alamat ini digunakan untuk menandai proses yang memiliki benang dari ruang alamat memori.

  • Thread dapat mendahului (terganggu).
  • Di thread lain yang berjalan, benang dapat diselenggarakan di penundaan (juga dikenal sebagai tidur) - ini adalah benang konsesi.

Benang dapat dibagi menjadi:

  • kernel thread: sistem operasi kernel diciptakan dan dihancurkan.
  • Pengguna thread: dukungan kernel dan tidak memerlukan program pengguna dilaksanakan benang.

Python3 benang merah dua modul:

  • _thread
  • threading (dianjurkan)

Modul benang telah ditinggalkan. Pengguna dapat menggunakan modul threading sebagai gantinya. Jadi, di Python3 tidak bisa lagi menggunakan "thread" modul. Untuk kompatibilitas, Python3 benang akan mengubah nama "_thread".


Mulai belajar Python benang

benang Python digunakan dalam dua cara: dengan fungsi atau kelas untuk membungkus objek benang.

Fungsional: Call _thread modul start_new_thread () berfungsi untuk menghasilkan benang baru. Sintaksnya adalah sebagai berikut:

_thread.start_new_thread ( function, args[, kwargs] )

Parameter Deskripsi:

  • Fungsi - fungsi benang.
  • args - parameter benang dilewatkan ke fungsi, ia harus menjadi tipe tuple.
  • kwargs - Opsional.

contoh:

#!/usr/bin/python3

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: 无法启动线程")

while 1:
   pass

Hasil output program di atas adalah sebagai berikut:

Thread-1: Wed Apr  6 11:36:31 2016
Thread-1: Wed Apr  6 11:36:33 2016
Thread-2: Wed Apr  6 11:36:33 2016
Thread-1: Wed Apr  6 11:36:35 2016
Thread-1: Wed Apr  6 11:36:37 2016
Thread-2: Wed Apr  6 11:36:37 2016
Thread-1: Wed Apr  6 11:36:39 2016
Thread-2: Wed Apr  6 11:36:41 2016
Thread-2: Wed Apr  6 11:36:45 2016
Thread-2: Wed Apr  6 11:36:49 2016

Setelah menjalankan proses di atas dapat menekan ctrl-c untuk keluar.


threading modul

Python3 memberikan dukungan untuk threading melalui dua _thread perpustakaan standar dan threading.

_thread menyediakan tingkat rendah, benang asli dan kunci sederhana, dibandingkan dengan modul fungsi threading masih relatif terbatas.

metode lain selain modul threading berisi modul _thread semua metode, tetapi juga untuk memberikan:

  • threading.currentThread (): Mengembalikan variabel thread saat ini.
  • threading.enumerate (): Mengembalikan daftar thread berjalan mengandung. Mengacu menjalankan benang dimulai sebelum akhirnya, itu tidak termasuk benang sebelum memulai dan setelah penghentian.
  • threading.activeCount (): Mengembalikan jumlah thread yang sedang berjalan, dan len (threading.enumerate ()) memiliki hasil yang sama.

Selain penggunaan metode, modul threading juga menyediakan kelas Thread untuk menangani benang, kelas Thread memberikan metode berikut:

  • menjalankan (): untuk menunjukkan metode benang aktif.
  • mulai (): memulai aktivitas benang.

  • bergabung ([waktu]): Tunggu sampai benang dibatalkan.Ini blok thread memanggil sampai metode thread ini bergabung () disebut suspensi - keluar normal atau membuang pengecualian tertangani - atau batas waktu opsional terjadi.
  • IsAlive (): Mengembalikan benang aktif.
  • getName (): Mengembalikan nama benang.
  • setName (): Mengatur nama benang.

Menggunakan modul threading untuk membuat sebuah thread

Kami dapat dibuat langsung diwarisi dari threading.Thread sub-kelas baru, setelah panggilan awal dan instantiate () metode untuk memulai thread baru, yang disebutnya (metode thread run):

#!/usr/bin/python3

import threading
import time

exitFlag = 0

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 ("开始线程:" + self.name)
        print_time(self.name, self.counter, 5)
        print ("退出线程:" + self.name)

def print_time(threadName, delay, counter):
    while counter:
        if exitFlag:
            threadName.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()
thread1.join()
thread2.join()
print ("退出主线程")

Hasil eksekusi program di atas adalah sebagai berikut;

开始线程:Thread-1
开始线程:Thread-2
Thread-1: Wed Apr  6 11:46:46 2016
Thread-1: Wed Apr  6 11:46:47 2016
Thread-2: Wed Apr  6 11:46:47 2016
Thread-1: Wed Apr  6 11:46:48 2016
Thread-1: Wed Apr  6 11:46:49 2016
Thread-2: Wed Apr  6 11:46:49 2016
Thread-1: Wed Apr  6 11:46:50 2016
退出线程:Thread-1
Thread-2: Wed Apr  6 11:46:51 2016
Thread-2: Wed Apr  6 11:46:53 2016
Thread-2: Wed Apr  6 11:46:55 2016
退出线程:Thread-2
退出主线程

Thread Sinkronisasi

Jika beberapa benang dari modifikasi data umum, hasil yang tak terduga mungkin terjadi, dalam rangka untuk memastikan keakuratan data, kita harus melakukan sinkronisasi beberapa thread.

objek thread menggunakan Lock dan Rlock dapat mencapai sinkronisasi thread sederhana, dua benda ini metode memperoleh dan metode rilis, bagi mereka yang membutuhkan setiap memungkinkan hanya satu data operasional benang, dapat ditempatkan dalam operasi memperoleh dan melepaskan metode dari kamar. Sebagai berikut:

Multithreading keuntungan adalah bahwa hal itu secara bersamaan dapat menjalankan beberapa tugas (setidaknya terasa seperti ini). Tapi ketika benang perlu berbagi data, mungkin tidak ada masalah sinkronisasi data.

Pertimbangkan kasus: daftar semua elemen adalah nol, benang "set" dari belakang ke depan semua elemen menjadi satu, dan benang "cetak" dari depan ke belakang yang bertugas membaca daftar dan cetak.

Kemudian, benang dapat "diatur" mulai berubah ketika thread "print" untuk mencetak daftar, itu akan menjadi setengah output dari setengah 0, yang data tidak disinkronkan. Untuk menghindari situasi ini, kami memperkenalkan konsep kunci.

Kunci memiliki dua negara - terkunci dan terkunci. Setiap kali thread seperti "set" untuk mengakses data bersama, Anda harus terlebih dahulu mendapatkan kunci, jika Anda sudah memiliki thread yang lain, seperti "print" untuk mendapatkan terkunci, kemudian membiarkan benang "mengatur" jeda, yang memblokir sinkron; menunggu sampai thread " mencetak "akses selesai, setelah rilis kunci, biarkan thread" set "untuk melanjutkan.

Setelah proses ini, ketika Anda mencetak daftar semua keluaran 0 atau 1 output penuh, tidak lagi muncul setengah malu 0 1 setengah.

contoh:

#!/usr/bin/python3

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 ("开启线程: " + self.name)
        # 获取锁,用于线程同步
        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 ("退出主线程")

Program di atas, output adalah:

开启线程: Thread-1
开启线程: Thread-2
Thread-1: Wed Apr  6 11:52:57 2016
Thread-1: Wed Apr  6 11:52:58 2016
Thread-1: Wed Apr  6 11:52:59 2016
Thread-2: Wed Apr  6 11:53:01 2016
Thread-2: Wed Apr  6 11:53:03 2016
Thread-2: Wed Apr  6 11:53:05 2016
退出主线程

antrian prioritas thread (Antrian)

modul Antrian Python menyediakan sinkronisasi, kelas antrian benang-aman, termasuk FIFO (first in first out) Antrian antrian, LIFO (bertahan, keluar pertama) LifoQueue antrian, dan PriorityQueue antrian prioritas.

antrian ini diimplementasikan mengunci primitif dapat digunakan secara langsung dalam multithreaded, Anda dapat menggunakan antrian untuk mencapai sinkronisasi antara benang.

Modul antrian metode yang umum digunakan:

  • Queue.qsize () mengembalikan ukuran antrian
  • Queue.empty () jika antrian kosong, kembali Benar, Salah dan sebaliknya
  • Queue.full () Jika antrian penuh, kembali Benar, False dan sebaliknya
  • Sesuai dengan ukuran dan maxsize Queue.full
  • Queue.get ([blok [, batas waktu]]) Mendapat antrian, waktu tunggu tunggu
  • Queue.get_nowait () bukan Queue.get (False)
  • Queue.put (item) menulis antrian, batas waktu menunggu waktu
  • Queue.put_nowait (item) cukup Queue.put (item, False)
  • Queue.task_done () setelah selesainya pekerjaan, Queue.task_done () fungsi mengirimkan sinyal untuk tugas telah selesai antrian
  • Queue.join () benar-benar berarti sampai antrian kosong, kemudian melakukan operasi lain

contoh:

#!/usr/bin/python3

import queue
import threading
import time

exitFlag = 0

class myThread (threading.Thread):
    def __init__(self, threadID, name, q):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.q = q
    def run(self):
        print ("开启线程:" + self.name)
        process_data(self.name, self.q)
        print ("退出线程:" + self.name)

def process_data(threadName, q):
    while not exitFlag:
        queueLock.acquire()
        if not workQueue.empty():
            data = q.get()
            queueLock.release()
            print ("%s processing %s" % (threadName, data))
        else:
            queueLock.release()
        time.sleep(1)

threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = queue.Queue(10)
threads = []
threadID = 1

# 创建新线程
for tName in threadList:
    thread = myThread(threadID, tName, workQueue)
    thread.start()
    threads.append(thread)
    threadID += 1

# 填充队列
queueLock.acquire()
for word in nameList:
    workQueue.put(word)
queueLock.release()

# 等待队列清空
while not workQueue.empty():
    pass

# 通知线程是时候退出
exitFlag = 1

# 等待所有线程完成
for t in threads:
    t.join()
print ("退出主线程")

Hasil dari program di atas:

开启线程:Thread-1
开启线程:Thread-2
开启线程:Thread-3
Thread-3 processing One
Thread-1 processing Two
Thread-2 processing Three
Thread-3 processing Four
Thread-1 processing Five
退出线程:Thread-3
退出线程:Thread-2
退出线程:Thread-1
退出主线程