آموزش پیاده سازی رشته در همزمانی پایتون
آموزش پیاده سازی رشته در همزمانی پایتون
در این درس از مجموعه آموزش برنامه نویسی سایت سورس باران، به آموزش پیاده سازی رشته در همزمانی پایتون خواهیم پرداخت.
در این درس، ما می آموزیم که چگونه رشته را در پایتون پیاده سازی کنیم.
پیشنهاد ویژه : پکیج آموزش پایتون
ماژول پایتون برای پیاده سازی رشته در همزمانی پایتون
به رشته های پایتون گاهی اوقات فرآیندهای سبک گفته می شود زیرا رشته ها حافظه بسیار کمتری نسبت به پردازش ها را اشغال می کنند. رشته ها امکان انجام همزمان چندین کار را دارند. در پایتون ، ما دو ماژول زیر را داریم که رشته ها را در یک برنامه پیاده سازی می کند –
- _thread>module>
- threading>module>
تفاوت اصلی این دو ماژول در این است که ماژول <_thread> یک موضوع را به عنوان یک تابع در نظر می گیرد در حالی که، ماژول <threading> هر موضوع را به عنوان یک شی در نظر می گیرد و آن را به روش شی گرا پیاده سازی می کند. علاوه بر این ، ماژول <_thread> در رزوه کاری سطح پایین موثر است و قابلیت های کمتری نسبت به ماژول <threading> دارد.
_thread>module>_ آموزش پیاده سازی رشته در همزمانی پایتون
در نسخه قبلی پایتون ، ماژول <thread> را داشتیم اما مدت طولانی است که آن را “منسوخ” می دانند. به کاربران توصیه شده است که به جای آن از ماژول <threading> استفاده کنند. بنابراین، در پایتون 3 ماژول “thread” دیگر در دسترس نیست. به دلیل ناسازگاری رو به عقب در Python3 به “<_thread>” تغییر نام داده است.
برای تولید رشته جدید با کمک ماژول <_thread>، باید روش start_new_thread آن را فراخوانی کنیم. عملکرد این روش را می توان با کمک نحو زیر درک کرد –
1 |
_thread.start_new_thread ( function, args[, kwargs] ) |
- args یک استدلال است
- kwargs یک دیکشنری اختیاری از استدلال های کلمات کلیدی است
اگر می خواهیم بدون عبور از آرگومان تابع را فراخوانی کنیم ، لازم است از یک استدلال خالی از آرگومان ها در args استفاده کنیم.
فراخوانی این روش بلافاصله برمی گردد، رشته کودک شروع می شود و فراخوانی تابع ها با لیست عبور داده شده از args است. موضوع در صورت بازگشت تابع خاتمه می یابد.
مثال
در زیر مثالی برای تولید رشته جدید با استفاده از ماژول <_thread> آورده شده است. ما در اینجا از متد ()start_new_thread استفاده می کنیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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: unable to start thread") while 1: pass |
خروجی
خروجی زیر به ما کمک می کند تا با کمک ماژول <_thread> تولید رشته جدید را درک کنیم
1 2 3 4 5 6 7 8 9 10 |
Thread-1: Mon Apr 23 10:03:33 2018 Thread-2: Mon Apr 23 10:03:35 2018 Thread-1: Mon Apr 23 10:03:35 2018 Thread-1: Mon Apr 23 10:03:37 2018 Thread-2: Mon Apr 23 10:03:39 2018 Thread-1: Mon Apr 23 10:03:39 2018 Thread-1: Mon Apr 23 10:03:41 2018 Thread-2: Mon Apr 23 10:03:43 2018 Thread-2: Mon Apr 23 10:03:47 2018 Thread-2: Mon Apr 23 10:03:51 2018 |
threading> module>
ماژول <threading> به روش شی گرا پیاده سازی می شود و هر رشته را به عنوان یک شیs در نظر می گیرد. بنابراین پشتیبانی از سطح بسیار قدرتمندتری نسبت به ماژول <_thread> برای موضوعات فراهم می کند. این ماژول با پایتون 2.4 همراه است.
متدهای اضافی در ماژول <threading>
ماژول <threading> شامل همه روشهای ماژول <_thread> است اما روشهای دیگری را نیز ارائه می دهد. روش های اضافی به شرح زیر است –
- ()threading.activeCount – این روش تعداد اشیای موضوع فعال را برمی گرداند
- ()threading.currentThread – این روش تعداد اشیا رشته موجود در کنترل موضوع فراخوان کننده را برمی گرداند.
- ()threading.enumerate – این روش لیستی از تمام اشیا رشته موضوعی را که در حال حاضر فعال هستند باز می گرداند.
برای پیاده سازی رشته، ماژول <threading> دارای کلاس رشته است که روش های زیر را ارائه می دهد –
()run – متد ()run نقطه ورود یک رشته است.
()start – متد ()start با فراخوانی متد run یک رشته را شروع می کند.
()join ([time]) – join منتظر خاتمه رشته ها است.
()isAlive – متد ()isAlive بررسی می کند که آیا یک رشته هنوز در حال اجرا است.
()getName – متد ()getName نام یک موضوع را برمی گرداند.
()setName – متد ()setName نام رشته ای را تنظیم می کند.
چگونه می توان با استفاده از ماژول <threading> رشته ایجاد کرد؟
در این بخش، ما می آموزیم که چگونه موضوعات را با استفاده از ماژول <threading> ایجاد کنیم. برای ایجاد یک موضوع جدید با استفاده از ماژول <threading> این مراحل را دنبال کنید –
مرحله 1 – در این مرحله، ما باید یک زیر کلاس جدید از کلاس Thread تعریف کنیم.
مرحله 2 – سپس برای اضافه کردن آرگومان های اضافی، باید متد ( __init __ (self [، args] را نادیده بگیریم.
مرحله 3 – در این مرحله، ما باید متد (run (self [، args]) را نادیده بگیریم تا آنچه را که رشته باید هنگام شروع انجام دهد ، پیاده سازی کنیم.
حال ، پس از ایجاد زیر کلاس Thread جدید، می توانیم نمونه ای از آن را ایجاد کرده و سپس با فراخوانی ()start که به نوبه خود متد ()run نامیده می شود ، یک رشته جدید شروع کنیم.
مثال
برای یادگیری نحوه تولید یک موضوع جدید با استفاده از ماژول <threading> این مثال را در نظر بگیرید.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
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, self.counter, 5) print ("Exiting " + 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 ("Exiting Main Thread") Starting Thread-1 Starting Thread-2 |
خروجی
اکنون، خروجی زیر را در نظر بگیرید –
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Thread-1: Mon Apr 23 10:52:09 2018 Thread-1: Mon Apr 23 10:52:10 2018 Thread-2: Mon Apr 23 10:52:10 2018 Thread-1: Mon Apr 23 10:52:11 2018 Thread-1: Mon Apr 23 10:52:12 2018 Thread-2: Mon Apr 23 10:52:12 2018 Thread-1: Mon Apr 23 10:52:13 2018 Exiting Thread-1 Thread-2: Mon Apr 23 10:52:14 2018 Thread-2: Mon Apr 23 10:52:16 2018 Thread-2: Mon Apr 23 10:52:18 2018 Exiting Thread-2 Exiting Main Thread |
برنامه پایتون برای حالت های رشته های مختلف
پنج حالت رشته وجود دارد – جدید، قابل اجرا، در حال اجرا، انتظار و خاتمه یافته. در میان این پنج مورد، ما بیشتر به سه حالت متمرکز خواهیم شد – در حال اجرا،، انتظار و خاتمه یافته. یک رشته منابع خود را در حالت در حال اجرا پیدا می کند ، منتظر منابع در حالت انتظار است. در صورت اجرا و به دست آوردن ، انتشار نهایی منبع در حالت مرده است.
برنامه پایتون زیر با کمک متد های ()start() sleep و ()join نشان می دهد که یک رشته به ترتیب در حالت های در حال اجرا ، انتظار و خاتمه یافته وارد شده است.
مرحله 1 – ماژول های لازم، <threading> و <time> را وارد کنید
1 2 |
import threading import time |
مرحله 2 – تابعی را تعریف کنید که هنگام ایجاد یک رشته فراخوانی شود.
1 2 |
def thread_states(): print("Thread entered in running state") |
مرحله 3 – ما از متد ()sleep ماژول زمان استفاده می کنیم تا موضوع خود را برای مدت زمان 2 ثانیه منتظر بماند.
1 |
time.sleep(2) |
مرحله 4 – اکنون ، ما یک رشته به نام T1 ایجاد می کنیم، که آرگومان تابع تعریف شده در بالا را می گیرد.
1 |
T1 = threading.Thread(target=thread_states) |
مرحله 5 – اکنون با کمک تابع ()start می توانیم رشته خود را شروع کنیم. این پیامی را ایجاد می کند که هنگام تعیین عملکرد توسط ما تنظیم شده است.
1 2 |
T1.start() Thread entered in running state |
مرحله 6 – اکنون، سرانجام می توانیم نخ را با استفاده از روش join () پس از پایان اجرای آن ، از بین ببریم.
1 |
T1.join() |
شروع یک رشته در پایتون
در پایتون، ما می توانیم یک رشته جدید را با روش های مختلف شروع کنیم، اما تعریف آسان آن به عنوان یک تابع تنها در میان آنها است. پس از تعریف تابع ما می توانیم این را به عنوان هدف برای یک رشته جدید منتقل کنیم. موضوع موضوع و غیره. کد پایتون زیر را اجرا کنید تا نحوه تابع را درک کنید –
1 2 3 4 5 6 7 8 9 10 11 12 |
import threading import time import random def Thread_execution(i): print("Execution of Thread {} started\n".format(i)) sleepTime = random.randint(1,4) time.sleep(sleepTime) print("Execution of Thread {} finished".format(i)) for i in range(4): thread = threading.Thread(target=Thread_execution, args=(i,)) thread.start() print("Active Threads:" , threading.enumerate()) |
خروجی
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
Execution of Thread 0 started Active Threads: [<_MainThread(MainThread, started 6040)>, <HistorySavingThread(IPythonHistorySavingThread, started 5968)>, <Thread(Thread-3576, started 3932)>] Execution of Thread 1 started Active Threads: [<_MainThread(MainThread, started 6040)>, <HistorySavingThread(IPythonHistorySavingThread, started 5968)>, <Thread(Thread-3576, started 3932)>, <Thread(Thread-3577, started 3080)>] Execution of Thread 2 started Active Threads: [<_MainThread(MainThread, started 6040)>, <HistorySavingThread(IPythonHistorySavingThread, started 5968)>, <Thread(Thread-3576, started 3932)>, <Thread(Thread-3577, started 3080)>, <Thread(Thread-3578, started 2268)>] Execution of Thread 3 started Active Threads: [<_MainThread(MainThread, started 6040)>, <HistorySavingThread(IPythonHistorySavingThread, started 5968)>, <Thread(Thread-3576, started 3932)>, <Thread(Thread-3577, started 3080)>, <Thread(Thread-3578, started 2268)>, <Thread(Thread-3579, started 4520)>] Execution of Thread 0 finished Execution of Thread 1 finished Execution of Thread 2 finished Execution of Thread 3 finished |
رشته های Daemon در پایتون
قبل از اجرای رشته های daemon در پایتون، باید در مورد رشتههای daemon و کاربرد آنها بدانیم. از نظر محاسبه، daemon یک فرایند پس زمینه است که درخواست های خدمات مختلف از جمله ارسال داده، انتقال فایل و غیره را کنترل می کند. همین کار را می توان با کمک موضوعات غیر daemon نیز انجام داد. با این حال، در این حالت موضوع اصلی باید به صورت دستی رشته های غیر Daemon را ردیابی کند. از طرف دیگر اگر ما از رشته های daemon استفاده می کنیم. رشته اصلی می تواند این مورد را کاملا فراموش کند و هنگام خروج رشته اصلی از بین می رود. نکته مهم دیگر در مورد موضوعات daemon این است که ما می توانیم از آنها فقط برای کارهای غیر ضروری استفاده کنیم که اگر کامل نشود یا در این بین کشته شود ، بر ما تأثیر نمی گذارد. در زیر نحوه اجرای موضوعات daemon در پایتون آورده شده است –
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import threading import time def nondaemonThread(): print("starting my thread") time.sleep(8) print("ending my thread") def daemonThread(): while True: print("Hello") time.sleep(2) if __name__ == '__main__': nondaemonThread = threading.Thread(target = nondaemonThread) daemonThread = threading.Thread(target = daemonThread) daemonThread.setDaemon(True) daemonThread.start() nondaemonThread.start() |
در کد بالا، دو تابع وجود دارد که عبارتند از> ()nondaemonThread و> ()daemonThread اولین تابع حالت خود را چاپ می کند و بعد از 8 ثانیه می خوابد در حالی که تابع ()deamonThread بعد از هر 2 ثانیه به طور نامحدود Hello را چاپ می کند. ما می توانیم تفاوت بین رشته های nondaemon و daemon را با کمک خروجی زیر درک کنیم.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Hello starting my thread Hello Hello Hello Hello ending my thread Hello Hello Hello Hello Hello |
دیدگاه شما