Python - Çok İş Parçacıklı Programlama

Birden fazla iş parçacığı çalıştırmak, aynı anda birkaç farklı programı çalıştırmaya benzer, ancak aşağıdaki avantajlara sahiptir:

  • Bir süreç içindeki birden çok iş parçacığı, ana iş parçacığı ile aynı veri alanını paylaşır ve bu nedenle, ayrı işlemler olmalarına göre daha kolay bilgi paylaşabilir veya birbirleriyle iletişim kurabilir.

  • İş parçacığı bazen hafif işlemler olarak adlandırılır ve fazla bellek yükü gerektirmezler; süreçlerden daha ucuzdurlar.

Bir iş parçacığının bir başlangıcı, bir yürütme sırası ve bir sonucu vardır. Şu anda bağlamında nerede çalıştığını takip eden bir yönerge işaretçisine sahiptir.

  • Önceden boşaltılabilir (kesintiye uğrayabilir)

  • Diğer iş parçacıkları çalışırken geçici olarak beklemeye alınabilir (uyku olarak da bilinir) - buna esneme denir.

Yeni Bir Konu Başlamak

Başka bir iş parçacığı oluşturmak için, iş parçacığı modülünde bulunan aşağıdaki yöntemi çağırmanız gerekir -

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

Bu yöntem çağrısı, hem Linux hem de Windows'ta yeni iş parçacıkları oluşturmanın hızlı ve verimli bir yolunu sağlar.

Yöntem çağrısı hemen döner ve çocuk evre başlar ve geçirilen argüman listesiyle işlevi çağırır . İşlev geri döndüğünde, iş parçacığı sona erer.

Burada args , argümanların bir demetidir; herhangi bir argüman iletmeden işlevi çağırmak için boş bir demet kullanın. kwargs , isteğe bağlı bir anahtar kelime argümanları sözlüğüdür .

Misal

#!/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

Yukarıdaki kod çalıştırıldığında, aşağıdaki sonucu verir -

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

Düşük seviyeli diş için çok etkilidir, fakat, ancak iplik modülü çok yeni diş modülüne göre sınırlıdır.

Threading Modülü

Python 2.4 ile birlikte gelen daha yeni diş açma modülü, önceki bölümde tartışılan diş modülünden çok daha güçlü, yüksek seviyeli destek sağlar.

Parçacığı modülü tüm yöntemler sunar iplik modülü ve bazı ek yöntemler sağlar -

  • threading.activeCount() - Aktif olan iş parçacığı nesnelerinin sayısını döndürür.

  • threading.currentThread() - Çağıranın iş parçacığı kontrolündeki iş parçacığı nesnelerinin sayısını döndürür.

  • threading.enumerate() - Şu anda aktif olan tüm iş parçacığı nesnelerinin bir listesini döndürür.

Yöntemlere ek olarak, threading modülü, threading uygulayan Thread sınıfına sahiptir. Thread sınıfı tarafından sağlanan yöntemler aşağıdaki gibidir -

  • run() - run () yöntemi, bir iş parçacığının giriş noktasıdır.

  • start() - start () yöntemi, çalıştırma yöntemini çağırarak bir iş parçacığı başlatır.

  • join([time]) - join (), iş parçacıklarının sona ermesini bekler.

  • isAlive() - isAlive () yöntemi, bir iş parçacığının hala yürütülmekte olup olmadığını kontrol eder.

  • getName() - getName () yöntemi bir iş parçacığının adını döndürür.

  • setName() - setName () yöntemi bir iş parçacığının adını belirler.

Diş Açma Modülünü Kullanarak Diş Oluşturma

Diş çekme modülünü kullanarak yeni bir diş oluşturmak için aşağıdakileri yapmanız gerekir -

  • Thread sınıfının yeni bir alt sınıfını tanımlayın .

  • Ek bağımsız değişkenler eklemek için __init __ (self [, args]) yöntemini geçersiz kılın .

  • Ardından, iş parçacığının başlatıldığında ne yapması gerektiğini uygulamak için run (self [, args]) yöntemini geçersiz kılın.

Yeni oluşturduktan sonra Konu alt sınıfı, bunu bir örneğini oluşturmak ve sonra da çağırarak yeni iş parçacığı başlayabilir start () sırayla aramaları, () çalıştırmak yöntemi.

Misal

#!/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"

Yukarıdaki kod çalıştırıldığında, aşağıdaki sonucu verir -

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

Konuları Senkronize Etme

Python ile sağlanan diş çekme modülü, iş parçacıkları senkronize etmenize olanak tanıyan, uygulaması kolay bir kilitleme mekanizması içerir. Yeni kilidi döndüren Lock () yöntemi çağrılarak yeni bir kilit oluşturulur .

Edinme (engelleme) Yeni kilit nesnesinin ait yöntem eş zamanlı olarak çalışacak şekilde mesajları zorlamak için kullanılır. İsteğe bağlı engelleme parametresi, iş parçacığının kilidi almak için bekleyip bekleyemeyeceğini kontrol etmenizi sağlar.

Eğer engelleme 0 olarak ayarlanır, bir 0 değeri ile iplik döner derhal kilit kazanılmış ve edilemezse ile kilit satın alınmıştır eğer 1. Engelleme 1 olarak ayarlanmışsa, iplik bloke olur ve kilidin açılmasını bekler.

Salma () , yeni kilit nesnesinin ait yöntem artık gereken zaman kilidi serbest bırakmak için kullanılır.

Misal

#!/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"

Yukarıdaki kod çalıştırıldığında, aşağıdaki sonucu verir -

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

Çok iş parçacıklı Öncelik Sırası

Kuyruk modülü öğeleri belirli sayıda tutabilir yeni bir kuyruk nesne oluşturmak için olanak sağlar. Kuyruğu kontrol etmek için aşağıdaki yöntemler vardır -

  • get() - get (), kuyruktan bir öğeyi kaldırır ve döndürür.

  • put() - Put, öğeyi bir kuyruğa ekler.

  • qsize() - qsize (), şu anda kuyrukta olan öğelerin sayısını döndürür.

  • empty()- Sıra boşsa empty () True döndürür; aksi takdirde, False.

  • full()- kuyruk doluysa full () True döndürür; aksi takdirde, False.

Misal

#!/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"

Yukarıdaki kod çalıştırıldığında, aşağıdaki sonucu verir -

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