Latest web development tutorials

Python3 خاصية تعدد

مواضيع متعددة تنفيذها في وقت واحد مشابه لعدد من البرامج المختلفة، وتشغيل مؤشرات والمزايا التالية:

  • يمكن استخدام المواضيع تشغل برنامج طويل في مهمة في الخلفية للتعامل معها.
  • قد يكون واجهة المستخدم أكثر جاذبية، وذلك على سبيل المثال قيام المستخدم بالنقر فوق الزر لتحريك بعض معالجة الحدث، يمكنك البوب ​​شريط التقدم لإظهار التقدم في عملية
  • يمكن تشغيل سرعة تسريع
  • على أدركت بعض المهام، مثل انتظار إدخال المستخدم، وثيقة محو الأمية والشبكة لإرسال واستقبال البيانات، وموضوع هو أكثر فائدة. في هذه الحالة، يمكننا أن يحرر بعض الموارد القيمة، مثل استخدام الذاكرة وهلم جرا.

المواضيع في عملية التنفيذ وعملية مختلفة. كل لديه موضوع منفصل تشغيل الدخول والخروج تسلسل والإجراءات اللازمة لتنفيذ هذا الأمر. ولكن موضوع غير قادر على أداء بشكل مستقل، فإنه يجب أن يكون موجودا وفقا للتطبيق، وتوفير المواضيع تنفيذ عدة يسيطر عليها التطبيق.

كل موضوع له مجموعة بلده من سجلات وحدة المعالجة المركزية، ودعا سياق الموضوع، يعكس سياق موضوع في الماضي البعيد للدولة موضوع وحدة المعالجة المركزية السجل.

مؤشر التعليمة ومؤشر مكدس سجلات هما أهم سجلات سياق موضوع وموضوع دائما يحصل على تشغيل في سياق هذه العملية، يتم استخدام هذه العناوين للاحتفال العملية التي تمتلك موضوع مساحة عنوان الذاكرة.

  • الموضوع يمكن استبقت (توقف).
  • في تشغل المواضيع الأخرى، ويمكن عقد الخيط معلقا (المعروف أيضا باسم النوم) - وهذا هو موضوع من التنازلات.

ويمكن تقسيم الموضوع إلى:

  • المواضيع النواة: نواة نظام التشغيل التي تم إنشاؤها وتدميرها.
  • المواضيع المستخدم: دعم النواة و لا يتطلب البرنامج المستخدم نفذت الموضوع.

Python3 القاسم المشترك وحدتين:

  • _thread
  • خيوط (موصى به)

وقد تم التخلي عن وحدة الموضوع. يمكن للمستخدمين استخدام وحدة الترابط بدلا من ذلك. لذلك، في Python3 لم تعد قادرة على استخدام "موضوع" وحدة. من أجل التوافق، وموضوع Python3 إعادة تسمية "_thread".


البدء في تعلم المواضيع بيثون

المواضيع الثعبان تستخدم بطريقتين: مع وظيفة أو فئة التفاف الكائن الموضوع.

وظيفية: دعوة _thread حدة وظيفة start_new_thread () لإنشاء موضوع جديد. بناء الجملة كما يلي:

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

المعلمة الوصف:

  • وظيفة - وظيفة موضوع.
  • وسائط - المعلمات موضوع تمريرها إلى وظيفة، لا بد له من أن يكون نوع الصفوف (tuple).
  • kwargs - اختياري.

على سبيل المثال:

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

نتائج الإخراج البرنامج المذكور أعلاه هي كما يلي:

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

بعد تنفيذ العملية المذكورة أعلاه يمكن أن تضغط على Ctrl-ج للخروج.


وحدة خيوط

Python3 تقديم الدعم لخيوط من خلال اثنين من _thread مكتبة معيار وخيوط.

يوفر _thread على مستوى منخفض، وموضوع الأصلي وقفل بسيط، فإنه تتم مقارنة إلى وحدة وظيفة خيوط لا تزال محدودة نسبيا.

طرق أخرى بالإضافة إلى وحدة الترابط يحتوي على وحدة _thread جميع الطرق، ولكن أيضا لتوفر:

  • threading.currentThread (): إرجاع متغير الترابط الحالي.
  • threading.enumerate (): إرجاع يحتوي على قائمة الموضوع قيد التشغيل. يشير تشغيل موضوع بدأ قبل النهاية، فإنه لا يشمل موضوع قبل البدء وبعد انتهاء.
  • threading.activeCount (): إرجاع عدد من المواضيع التي تعمل بنظام التشغيل، ولين (threading.enumerate ()) لديها نفس النتيجة.

بالإضافة إلى استخدام وسائل، ويوفر وحدة خيوط أيضا فئة الموضوع إلى معالجة موضوع، وتقدم الطبقة الموضوع الطرق التالية:

  • تشغيل (): للإشارة إلى طريقة المواضيع النشطة.
  • بدء (): بدء النشاط موضوع.

  • انضمام ([مرة]): انتظر حتى يتم إحباط الموضوع.هذا كتل يسمى موضوع الدعوة حتى طريقة لمؤشر الترابط انضمام () تعليق - خروج العادي أو رمي استثناء غير معالج - أو مهلة اختيارية يحدث.
  • isAlive (): إرجاع موضوع نشط.
  • getName (): إرجاع اسم الموضوع.
  • setName (): تعيين اسم الموضوع.

استخدام وحدة خيوط لخلق موضوع

نحن يمكن أن تنشأ الموروثة مباشرة من threading.Thread من الدرجة فرعية جديدة، بعد أسلوب البدء ومثيل (دعوة) لبدء موضوع جديد وتصفها المدى لمؤشر الترابط طريقة ():

#!/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 ("退出主线程")

نتائج تنفيذ البرنامج المذكور أعلاه هي على النحو التالي؛

开始线程: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
退出主线程

تزامن الموضوع

إذا مواضيع متعددة من تعديل بيانات المشترك، قد تحدث نتائج غير متوقعة، وذلك لضمان دقة البيانات، ونحن بحاجة لمزامنة مواضيع متعددة.

كائن الموضوع باستخدام قفل وRlock يمكن تحقيق التزامن موضوع بسيط، الكائنين وطرق اكتساب وأساليب الإفراج، بالنسبة لأولئك الذين يحتاجون إلى السماح لكل بيانات التشغيل موضوع واحد فقط، ويمكن وضعها في اكتساب عملية والافراج عن أساليب غرفة. على النحو التالي:

خاصية تعدد ميزة هو أنه يمكن تشغيلها في وقت واحد مهام متعددة (على الأقل يشعر مثل هذا). ولكن عندما المواضيع تحتاج لتبادل البيانات، قد تكون هناك قضايا مزامنة البيانات.

النظر في القضية: قائمة بجميع العناصر هي صفر، وموضوع "مجموعة" من الخلف إلى الأمام على جميع العناصر في واحدة، وموضوع "طباعة" من الأمام إلى الخلف المسؤول من قراءة القائمة، والطباعة.

ثم، في موضوع قد يكون "مجموعة" بدأت تتغير عندما موضوع "طباعة" لطباعة قائمة، سيكون من نصف الناتج من نصف 0، والذي لم يتم مزامنة البيانات. لتجنب هذا الوضع، ونحن نقدم مفهوم القفل.

قفل ديه دولتين - مؤمن وغير مؤمن. كلما موضوع مثل "مجموعة" للوصول إلى البيانات المشتركة، يجب أولا الحصول على التأمين، وإذا كان لديك بالفعل موضوع آخر، مثل "طباعة" لنسجن، ثم ترك موضوع "تعيين" وقفة، وهو حجب متزامن؛ انتظر حتى موضوع " طباعة "اكتمال وصول، وبعد الافراج عن قفل، والسماح للموضوع" مجموعة "للمتابعة.

بعد هذه العملية، عندما قمت بطباعة قائمة من كافة الإخراج إما 0 أو 1 الانتاج الكامل، لم يعد يظهر نصف الإحراج 0 1 نصف.

على سبيل المثال:

#!/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 ("退出主线程")

البرنامج المذكور أعلاه، والناتج هو:

开启线程: 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
退出主线程

طابور الأولوية الموضوع (انتظار)

وتقدم وحدة الصف بايثون التزامن، والطبقات طابور موضوع آمنة، بما في ذلك FIFO (الأول في الأول من) قائمة انتظار طابور، إل آي إف (آخر في، أولا خارج) LifoQueue طابور، وPriorityQueue طابور الأولوية.

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

وحدة الصف الأساليب المستخدمة شيوعا:

  • Queue.qsize () إرجاع حجم قائمة الانتظار
  • Queue.empty () إذا قائمة الانتظار فارغة، بإرجاع True، الكاذبة والعكس بالعكس
  • Queue.full () إذا كانت قائمة الانتظار الكامل، والعودة صحيح، خطأ والعكس بالعكس
  • المقابلة لحجم وماكس سايز Queue.full
  • Queue.get ([كتلة [، مهلة]]) يحصل على قائمة الانتظار مهلة انتظار الوقت المناسب
  • Queue.get_nowait () بدلا Queue.get (خطأ)
  • Queue.put (البند) طابور الكتابة، مهلة انتظار الوقت المناسب
  • Queue.put_nowait (البند) تماما Queue.put (البند، خطأ)
  • Queue.task_done () بعد الانتهاء من العمل، Queue.task_done () يرسل إشارة وظيفة لهذه المهمة قد اكتملت طابور
  • Queue.join () يعني حقا حتى قائمة الانتظار فارغة، ثم إجراء عمليات أخرى

على سبيل المثال:

#!/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 ("退出主线程")

نتائج البرنامج أعلاه:

开启线程: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
退出主线程