Python - Pemrograman Multithreaded

Menjalankan beberapa utas mirip dengan menjalankan beberapa program berbeda secara bersamaan, tetapi dengan manfaat berikut -

  • Beberapa utas dalam proses berbagi ruang data yang sama dengan utas utama dan oleh karena itu dapat berbagi informasi atau berkomunikasi satu sama lain dengan lebih mudah daripada jika mereka adalah proses terpisah.

  • Thread terkadang disebut proses ringan dan tidak membutuhkan banyak overhead memori; mereka lebih murah daripada proses.

Sebuah utas memiliki awal, urutan eksekusi, dan kesimpulan. Ini memiliki penunjuk instruksi yang melacak di mana dalam konteksnya saat ini berjalan.

  • Itu bisa lebih dulu (terputus)

  • Ini sementara dapat ditahan (juga dikenal sebagai tidur) sementara utas lain sedang berjalan - ini disebut menyerah.

Memulai Thread Baru

Untuk menelurkan utas lain, Anda perlu memanggil metode berikut yang tersedia di modul utas -

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

Panggilan metode ini memungkinkan cara yang cepat dan efisien untuk membuat utas baru di Linux dan Windows.

Pemanggilan metode segera kembali dan utas anak dimulai dan memanggil fungsi dengan daftar args yang diteruskan . Saat fungsi kembali, utas berhenti.

Di sini, args adalah tuple argumen; gunakan tupel kosong untuk memanggil fungsi tanpa memberikan argumen apa pun. kwargs adalah kamus opsional dari argumen kata kunci.

Contoh

#!/usr/bin/python

import thread
import time

# Define a function for the thread
def print_time( threadName, delay):
   count = 0
   while count < 5:
      time.sleep(delay)
      count += 1
      print "%s: %s" % ( threadName, time.ctime(time.time()) )

# Create two threads as follows
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

Ketika kode di atas dijalankan, itu menghasilkan hasil sebagai 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

Meskipun sangat efektif untuk penguliran tingkat rendah, tetapi modul ulir sangat terbatas dibandingkan dengan modul penguliran yang lebih baru.

The Threading Modul

Modul threading yang lebih baru yang disertakan dengan Python 2.4 memberikan dukungan tingkat tinggi yang jauh lebih kuat untuk utas daripada modul utas yang dibahas di bagian sebelumnya.

The threading modul mengekspos semua metode dari benang modul dan menyediakan beberapa metode tambahan -

  • threading.activeCount() - Mengembalikan jumlah objek utas yang aktif.

  • threading.currentThread() - Mengembalikan jumlah objek utas dalam kontrol utas pemanggil.

  • threading.enumerate() - Menampilkan daftar semua objek utas yang saat ini aktif.

Selain metodenya, modul threading memiliki kelas Thread yang mengimplementasikan threading. Metode yang disediakan oleh kelas Thread adalah sebagai berikut -

  • run() - Metode run () adalah titik masuk untuk utas.

  • start() - Metode start () memulai utas dengan memanggil metode run.

  • join([time]) - Join () menunggu utas berakhir.

  • isAlive() - Metode isAlive () memeriksa apakah utas masih dijalankan.

  • getName() - Metode getName () mengembalikan nama utas.

  • setName() - Metode setName () menetapkan nama utas.

Membuat Thread Menggunakan Modul Threading

Untuk mengimplementasikan utas baru menggunakan modul threading, Anda harus melakukan hal berikut -

  • Tentukan subclass baru dari kelas Thread .

  • Ganti metode __init __ (self [, args]) untuk menambahkan argumen tambahan.

  • Kemudian, ganti metode run (self [, args]) untuk mengimplementasikan apa yang harus dilakukan thread saat dimulai.

Setelah Anda membuat subkelas Thread baru , Anda dapat membuat instance darinya dan kemudian memulai thread baru dengan menjalankan metode start () , yang pada gilirannya akan memanggil metode run () .

Contoh

#!/usr/bin/python

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 "Starting " + self.name
      print_time(self.name, 5, self.counter)
      print "Exiting " + self.name

def print_time(threadName, counter, delay):
   while counter:
      if exitFlag:
         threadName.exit()
      time.sleep(delay)
      print "%s: %s" % (threadName, time.ctime(time.time()))
      counter -= 1

# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# Start new Threads
thread1.start()
thread2.start()

print "Exiting Main Thread"

Ketika kode di atas dijalankan, itu menghasilkan hasil sebagai berikut -

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

Sinkronisasi Thread

Modul threading yang disediakan oleh Python menyertakan mekanisme penguncian yang mudah diterapkan yang memungkinkan Anda untuk menyinkronkan utas. Kunci baru dibuat dengan memanggil metode Lock () , yang mengembalikan kunci baru.

Metode perolehan (pemblokiran) dari objek kunci baru digunakan untuk memaksa utas berjalan secara sinkron. Parameter pemblokiran opsional memungkinkan Anda untuk mengontrol apakah utas menunggu untuk mendapatkan kunci.

Jika pemblokiran diatur ke 0, utas segera kembali dengan nilai 0 jika kunci tidak dapat diperoleh dan dengan 1 jika kunci diperoleh. Jika pemblokiran diatur ke 1, utas akan memblokir dan menunggu kunci dilepaskan.

Metode release () dari objek kunci baru digunakan untuk melepaskan kunci saat tidak lagi diperlukan.

Contoh

#!/usr/bin/python

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
      # Get lock to synchronize threads
      threadLock.acquire()
      print_time(self.name, self.counter, 3)
      # Free lock to release next thread
      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 = []

# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# Start new Threads
thread1.start()
thread2.start()

# Add threads to thread list
threads.append(thread1)
threads.append(thread2)

# Wait for all threads to complete
for t in threads:
    t.join()
print "Exiting Main Thread"

Ketika kode di atas dijalankan, itu menghasilkan hasil sebagai berikut -

Starting Thread-1
Starting Thread-2
Thread-1: Thu Mar 21 09:11:28 2013
Thread-1: Thu Mar 21 09:11:29 2013
Thread-1: Thu Mar 21 09:11:30 2013
Thread-2: Thu Mar 21 09:11:32 2013
Thread-2: Thu Mar 21 09:11:34 2013
Thread-2: Thu Mar 21 09:11:36 2013
Exiting Main Thread

Antrean Prioritas Multithread

The Antrian modul memungkinkan Anda untuk membuat objek antrian baru yang dapat menampung jumlah tertentu item. Ada metode berikut untuk mengontrol Antrian -

  • get() - Get () menghapus dan mengembalikan item dari antrian.

  • put() - Put menambahkan item ke antrian.

  • qsize() - The qsize () mengembalikan jumlah item yang saat ini berada dalam antrian.

  • empty()- empty () mengembalikan True jika antrian kosong; jika tidak, Salah.

  • full()- full () mengembalikan True jika antrian penuh; jika tidak, Salah.

Contoh

#!/usr/bin/python

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 "Starting " + self.name
      process_data(self.name, self.q)
      print "Exiting " + 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

# Create new threads
for tName in threadList:
   thread = myThread(threadID, tName, workQueue)
   thread.start()
   threads.append(thread)
   threadID += 1

# Fill the queue
queueLock.acquire()
for word in nameList:
   workQueue.put(word)
queueLock.release()

# Wait for queue to empty
while not workQueue.empty():
   pass

# Notify threads it's time to exit
exitFlag = 1

# Wait for all threads to complete
for t in threads:
   t.join()
print "Exiting Main Thread"

Ketika kode di atas dijalankan, itu menghasilkan hasil sebagai berikut -

Starting Thread-1
Starting Thread-2
Starting Thread-3
Thread-1 processing One
Thread-2 processing Two
Thread-3 processing Three
Thread-1 processing Four
Thread-2 processing Five
Exiting Thread-3
Exiting Thread-1
Exiting Thread-2
Exiting Main Thread