برمجة العمليات الموزعة او المجزئة في بايثون بيثون Python Multithreaded Programming

برمجة العمليات الموزعة او المجزئة في بايثون بيثون

 Python  Multithreaded Programming

برمجة العمليات الموزعة او المجزئة في بايثون بيثون Python  Multithreaded Programming

يشبه تشغيل عدة مؤشرات ترابط تشغيل عدة برامج مختلفة بشكل متزامن ، ولكن مع الفوائد التالية -

 تتشارك مؤشرات الترابط المتعددة داخل العملية في نفس مساحة البيانات مع مؤشر الترابط الرئيسي ، وبالتالي يمكنها مشاركة المعلومات أو التواصل مع بعضها البعض بسهولة أكبر مما لو كانت عمليات منفصلة.

 الخيوط تسمى أحيانًا عمليات خفيفة الوزن ولا تتطلب الكثير من الذاكرة.  أنها أرخص من العمليات.

 يحتوي مؤشر الترابط على بداية وتسلسل تنفيذ وخاتمة.  يحتوي على مؤشر تعليمات يتتبع أين يتم تشغيله حاليًا ضمن السياق الخاص به.

 يمكن استباقها (مقاطعة)

 يمكن تعليقه مؤقتًا (يُعرف أيضًا باسم النوم) أثناء تشغيل مؤشرات الترابط الأخرى - وهذا ما يسمى بالرضا.

Starting a New Thread انشاء مهمة

لانشاء  مهمة آخرة ، تحتاج إلى استدعاء الطريقة التالية المتاحة في وحدة موضوع -
thread.start_new_thread ( function, args[, kwargs] )
تتيح هذه الطريقة استدعاء طريقة سريعة وفعالة لإنشاء مؤشرات ترابط جديدة في كل من Linux و Windows.

 إرجاع استدعاء الأسلوب على الفور ويبدأ مؤشر الترابط التابع ويعمل المكالمات مع قائمة args التي تم تمريرها.  عندما ترجع الوظيفة ، ينتهي الخيط.

 هنا ، الحجج هي مجموعة من الحجج.  استخدام tuple فارغة لاستدعاء وظيفة دون تمرير أي الحجج.  kwargs هو قاموس اختياري للوسائط الأساسية.

 مثال
#!/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
عند تنفيذ الكود أعلاه ، فإنه ينتج النتيجة التالية -
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
على الرغم من أنها فعالة للغاية بالنسبة للخيوط منخفضة المستوى ، إلا أن وحدة سلاسل الرسائل محدودة للغاية مقارنة بوحدة خيوط المعالجة الأحدث.

The Threading Module وحدة الترابط

توفر وحدة الترابط الأحدث المتضمنة في Python 2.4 دعمًا قويًا وعالي المستوى للخيوط أكثر من وحدة سلاسل الرسائل التي تمت مناقشتها في القسم السابق.

 تكشف وحدة الترابط عن جميع أساليب وحدة سلاسل الرسائل وتوفر بعض الطرق الإضافية -
  • threading.activeCount()
  •  − إرجاع عدد كائنات مؤشر الترابط النشطة.
  • threading.currentThread() 
  • - إرجاع عدد كائنات مؤشر الترابط في عنصر تحكم مؤشر ترابط المتصل.
  • threading.enumerate() −
  • إرجاع قائمة بكافة كائنات مؤشر الترابط النشطة حاليًا.

     بالإضافة إلى الطرق ، تحتوي وحدة الترابط على فئة مؤشر الترابط التي تقوم بتنفيذ الترابط.  الأساليب التي توفرها فئة مؤشر الترابط كالتالي -
  • run() − 
  • طريقة run () هي نقطة الدخول لمؤشر الترابط.
  • start() −
  •  طريقة start () تبدأ سلسلة من خلال استدعاء طريقة التشغيل.
  • join([time]) −
  •  الصلة () ينتظر مؤشرات الترابط لإنهاء.
  • isAlive() − يتحقق الأسلوب isAlive () ما إذا كان مؤشر ترابط ما زال قيد التنفيذ.
  • getName() − 
  • إرجاع الأسلوب getName () اسم مؤشر ترابط.
  • setName() − 
  • يعيّن الأسلوب setName () اسم مؤشر ترابط.

Creating Thread Using Threading Module

إنشاء مؤشر ترابط باستخدام وحدة الترابط
لتنفيذ سلسلة رسائل جديدة باستخدام وحدة الترابط ، عليك القيام بما يلي -

 تحديد فئة فرعية جديدة من فئة مؤشر الترابط.

 تجاوز الأسلوب __init __ (self [، ​​args]) لإضافة وسيطات إضافية.

 ثم ، تجاوز أسلوب التشغيل (self [، ​​args]) لتطبيق ما يجب أن يفعله مؤشر الترابط عند بدء تشغيله.

 بمجرد إنشاء فئة فرعية لمؤشر الترابط الجديد ، يمكنك إنشاء مثيل لها ثم بدء تشغيل مؤشر ترابط جديد عن طريق استدعاء بداية () ، والتي بدورها تستدعي طريقة تشغيل ().

 مثال
#!/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"

عندما يتم تنفيذ الرمز أعلاه ، فإنه ينتج
 النتيجة التالية -
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

Synchronizing Threads

مزامنة المهام او العمليات
تتضمن وحدة الترابط  threads المتوفرة مع Python آلية قفل بسيطة التنفيذ تسمح لك بمزامنة مؤشرات الترابط.  يتم إنشاء قفل جديد عن طريق استدعاء الأسلوب Lock () ، والذي يقوم بإرجاع القفل الجديد.
 يتم استخدام طريقة الحصول على (حظر) لكائن القفل الجديد لفرض مؤشرات الترابط على التشغيل بشكل متزامن.  تتيح لك معلمة الحظر الاختيارية التحكم في ما إذا كان مؤشر الترابط ينتظر الحصول على القفل.
 إذا تم ضبط الحظر على 0 ، فسيعود مؤشر الترابط على الفور بقيمة 0 إذا تعذر الحصول على القفل ورقم 1 إذا تم الحصول على القفل.  إذا تم ضبط الحظر على 1 ، فإن كتل الخيوط وانتظر قفل القفل.
 يتم استخدام طريقة release () لكائن القفل الجديد لتحرير القفل عندما لم يعد مطلوبًا.
 مثال
#!/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"
عندما يتم تنفيذ الرمز أعلاه ، فإنه ينتج
 النتيجة التالية -
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

Multithreaded Priority Queue قائمة الأولويات في العمليات الموزعة

تسمح لك وحدة قائمة الانتظار بإنشاء كائن قائمة انتظار جديد يمكنه استيعاب عدد معين من العناصر.  هناك طرق التالية للتحكم في قائمة الانتظار -
  • get() −
  •  get () يزيل ويعيد عنصر من قائمة الانتظار.
  • put() − 
  • يضيف وضع عنصر إلى قائمة انتظار.
  • qsize() −
  • تعيد qsize () عدد العناصر الموجودة حاليا في قائمة الانتظار.
  • empty() −
  •  فارغة () بإرجاع True إذا كانت قائمة الانتظار فارغة؛  خلاف ذلك ، خطأ.
  • full()  
  • the full () تُرجع True إذا كانت قائمة الانتظار ممتلئة ؛  خلاف ذلك ، خطأ.

  •  مثال
#!/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"
عند تنفيذ الكود أعلاه ، فإنه ينتج النتيجة التالية -
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