آموزش پیاده سازی رشته در همزمانی پایتون

3 سال پیش

آموزش پیاده سازی رشته در همزمانی پایتون

در این درس از مجموعه آموزش برنامه نویسی سایت سورس باران، به آموزش پیاده سازی رشته در همزمانی پایتون خواهیم پرداخت.

در این درس، ما می آموزیم که چگونه رشته را در پایتون پیاده سازی کنیم.

پیشنهاد ویژه : پکیج آموزش پایتون

ماژول پایتون برای پیاده سازی رشته در همزمانی پایتون

به رشته های پایتون گاهی اوقات فرآیندهای سبک گفته می شود زیرا رشته ها حافظه بسیار کمتری نسبت به پردازش ها را اشغال می کنند. رشته ها امکان انجام همزمان چندین کار را دارند. در پایتون ، ما دو ماژول زیر را داریم که رشته ها را در یک برنامه پیاده سازی می کند –

  • _thread>module>
  • threading>module>

 

تفاوت اصلی این دو ماژول در این است که ماژول <_thread> یک موضوع را به عنوان یک تابع در نظر می گیرد در حالی که، ماژول <threading> هر موضوع را به عنوان یک شی در نظر می گیرد و آن را به روش شی گرا پیاده سازی می کند. علاوه بر این ، ماژول <_thread> در رزوه کاری سطح پایین موثر است و قابلیت های کمتری نسبت به ماژول <threading> دارد.

_thread>module>_   آموزش پیاده سازی رشته در همزمانی پایتون

در نسخه قبلی پایتون ، ماژول <thread> را داشتیم اما مدت طولانی است که آن را “منسوخ” می دانند. به کاربران توصیه شده است که به جای آن از ماژول <threading> استفاده کنند. بنابراین، در پایتون ۳ ماژول “thread” دیگر در دسترس نیست. به دلیل ناسازگاری رو به عقب در Python3 به “<_thread>” تغییر نام داده است.

برای تولید رشته جدید با کمک ماژول <_thread>، باید روش start_new_thread آن را فراخوانی کنیم. عملکرد این روش را می توان با کمک نحو زیر درک کرد –

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

 

  • args یک استدلال است
  • kwargs یک دیکشنری اختیاری از استدلال های کلمات کلیدی است

 

اگر می خواهیم بدون عبور از آرگومان تابع را فراخوانی کنیم ، لازم است از یک استدلال خالی از آرگومان ها در args استفاده کنیم.

فراخوانی این روش بلافاصله برمی گردد، رشته کودک شروع می شود و فراخوانی تابع ها با لیست عبور داده شده از args است. موضوع در صورت بازگشت تابع خاتمه می یابد.

مثال

در زیر مثالی برای تولید رشته جدید با استفاده از ماژول <_thread> آورده شده است. ما در اینجا از متد ()start_new_thread استفاده می کنیم.

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> تولید رشته جدید را درک کنیم

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> برای موضوعات فراهم می کند. این ماژول با پایتون ۲٫۴ همراه است.

متدهای اضافی در ماژول <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> این مراحل را دنبال کنید –

مرحله ۱ – در این مرحله، ما باید یک زیر کلاس جدید از کلاس Thread تعریف کنیم.

مرحله ۲ – سپس برای اضافه کردن آرگومان های اضافی، باید متد ( __init __ (self [، ​​args] را نادیده بگیریم.

مرحله ۳ – در این مرحله، ما باید متد (run (self [، ​​args]) را نادیده بگیریم تا آنچه را که رشته باید هنگام شروع انجام دهد ، پیاده سازی کنیم.

حال ، پس از ایجاد زیر کلاس Thread جدید، می توانیم نمونه ای از آن را ایجاد کرده و سپس با فراخوانی ()start که به نوبه خود متد ()run نامیده می شود ، یک رشته جدید شروع کنیم.

مثال

برای یادگیری نحوه تولید یک موضوع جدید با استفاده از ماژول <threading> این مثال را در نظر بگیرید.

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

 

خروجی

اکنون، خروجی زیر را در نظر بگیرید –

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 نشان می دهد که یک رشته به ترتیب در حالت های در حال اجرا ، انتظار و خاتمه یافته وارد شده است.

 

مرحله ۱ – ماژول های لازم، <threading> و <time> را وارد کنید

import threading
import time

 

مرحله ۲ – تابعی را تعریف کنید که هنگام ایجاد یک رشته فراخوانی شود.

def thread_states():
   print("Thread entered in running state")

 

مرحله ۳ – ما از متد ()sleep  ماژول زمان استفاده می کنیم تا موضوع خود را برای مدت زمان ۲ ثانیه منتظر بماند.

time.sleep(2)

 

مرحله ۴ – اکنون ، ما یک رشته به نام T1 ایجاد می کنیم، که آرگومان تابع تعریف شده در بالا را می گیرد.

T1 = threading.Thread(target=thread_states)

مرحله ۵ – اکنون با کمک تابع ()start می توانیم رشته خود را شروع کنیم. این پیامی را ایجاد می کند که هنگام تعیین عملکرد توسط ما تنظیم شده است.

T1.start()
Thread entered in running state

 

مرحله ۶ – اکنون، سرانجام می توانیم نخ را با استفاده از روش join () پس از پایان اجرای آن ، از بین ببریم.

T1.join()

 

شروع یک رشته در پایتون

در پایتون، ما می توانیم یک رشته جدید را با روش های مختلف شروع کنیم، اما تعریف آسان آن به عنوان یک تابع تنها در میان آنها است. پس از تعریف تابع ما می توانیم این را به عنوان هدف برای یک رشته جدید منتقل کنیم. موضوع موضوع و غیره. کد پایتون زیر را اجرا کنید تا نحوه تابع را درک کنید –

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())

 

خروجی

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 در پایتون آورده شده است –

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  اولین تابع حالت خود را چاپ می کند و بعد از ۸ ثانیه می خوابد در حالی که تابع ()deamonThread  بعد از هر ۲ ثانیه به طور نامحدود Hello را چاپ می کند. ما می توانیم تفاوت بین رشته های nondaemon و daemon را با کمک خروجی زیر درک کنیم.

 

Hello

starting my thread
Hello
Hello
Hello
Hello
ending my thread
Hello
Hello
Hello
Hello
Hello

 

منبع.

لیست جلسات قبل آموزش همزبانی در پایتون

  1. آموزش همزمانی در برنامه نویسی پایتون
  2. آموزش همزمانی در برنامه نویسی پایتون _ مقدمه
  3. آموزش معماری سیستم و حافظه در برنامه نویسی پایتون
  4.  آموزش رشته ها در همزمانی پایتون 
0
برچسب ها :
نویسنده مطلب erfan molaei

دیدگاه شما

بدون دیدگاه