पायथन 3 - मल्टीथ्रेडेड प्रोग्रामिंग
कई धागे चलाना समवर्ती रूप से कई अलग-अलग कार्यक्रमों को चलाने के समान है, लेकिन निम्नलिखित लाभ के साथ -
एक प्रक्रिया के भीतर कई थ्रेड्स मुख्य थ्रेड के साथ एक ही डेटा स्पेस साझा करते हैं और इसलिए जानकारी साझा कर सकते हैं या एक दूसरे के साथ आसानी से संवाद कर सकते हैं यदि वे अलग-अलग प्रक्रियाएं हैं।
थ्रेड्स को कभी-कभी हल्के वजन की प्रक्रिया कहा जाता है और उन्हें अधिक मेमोरी ओवरहेड की आवश्यकता नहीं होती है; वे प्रक्रियाओं की तुलना में सस्ते हैं।
एक धागे में एक शुरुआत, एक निष्पादन अनुक्रम और एक निष्कर्ष है। इसमें एक निर्देश सूचक है जो अपने संदर्भ में जहां यह वर्तमान में चल रहा है, का ट्रैक रखता है।
यह पूर्व-खाली (बाधित) हो सकता है।
इसे अस्थायी रूप से होल्ड पर रखा जा सकता है (जिसे नींद के रूप में भी जाना जाता है) जबकि अन्य धागे चल रहे हैं - इसे उपज कहा जाता है।
दो अलग-अलग प्रकार के धागे हैं -
- गिरी धागा
- उपयोगकर्ता धागा
कर्नेल थ्रेड्स ऑपरेटिंग सिस्टम का एक हिस्सा हैं, जबकि कर्नेल में यूजर-स्पेस थ्रेड्स को लागू नहीं किया जाता है।
दो मॉड्यूल हैं जो पायथन 3 में धागे के उपयोग का समर्थन करते हैं -
- _thread
- threading
थ्रेड मॉड्यूल काफी लंबे समय के लिए "पदावनत" किया गया है। उपयोगकर्ताओं को इसके बजाय थ्रेडिंग मॉड्यूल का उपयोग करने के लिए प्रोत्साहित किया जाता है। इसलिए, पायथन 3 में, मॉड्यूल "थ्रेड" अब उपलब्ध नहीं है। हालाँकि, इसका नाम बदलकर "_thread" किया गया है, जिसे Python3 में बैकवर्ड कॉम्पिटिशन के लिए रखा गया है।
एक नया सूत्र शुरू करना
एक और धागा स्पॉन करने के लिए, आपको थ्रेड मॉड्यूल में उपलब्ध निम्न विधि को कॉल करना होगा -
_thread.start_new_thread ( function, args[, kwargs] )
यह विधि कॉल लिनक्स और विंडोज दोनों में नए धागे बनाने के लिए एक तेज और कुशल तरीका सक्षम करता है।
विधि कॉल तुरंत रिटर्न करती है और चाइल्ड थ्रेड शुरू होता है और आर्ग की पारित सूची के साथ कार्य करता है । जब फ़ंक्शन वापस आता है, तो थ्रेड समाप्त हो जाता है।
इधर, आर्ग तर्कों की किसी टपल है; किसी भी तर्क को पारित किए बिना फ़ंक्शन को कॉल करने के लिए एक खाली टपल का उपयोग करें। kwargs कीवर्ड तर्कों का एक वैकल्पिक शब्दकोश है।
उदाहरण
#!/usr/bin/python3
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: Fri Feb 19 09:41:39 2016
Thread-2: Fri Feb 19 09:41:41 2016
Thread-1: Fri Feb 19 09:41:41 2016
Thread-1: Fri Feb 19 09:41:43 2016
Thread-2: Fri Feb 19 09:41:45 2016
Thread-1: Fri Feb 19 09:41:45 2016
Thread-1: Fri Feb 19 09:41:47 2016
Thread-2: Fri Feb 19 09:41:49 2016
Thread-2: Fri Feb 19 09:41:53 2016
कार्यक्रम एक अनंत लूप में जाता है। रोकने के लिए आपको ctrl-c दबाना होगा
यद्यपि यह निम्न-स्तरीय थ्रेडिंग के लिए बहुत प्रभावी है, थ्रेड मॉड्यूल नए थ्रेडिंग मॉड्यूल की तुलना में बहुत सीमित है।
थ्रेडिंग मॉड्यूल
पायथन 2.4 के साथ शामिल नया थ्रेडिंग मॉड्यूल पिछले अनुभाग में चर्चा किए गए थ्रेड मॉड्यूल की तुलना में थ्रेड्स के लिए अधिक शक्तिशाली, उच्च-स्तरीय समर्थन प्रदान करता है।
सूत्रण मॉड्यूल के सभी तरीकों को उजागर करता है धागा मॉड्यूल और कुछ अतिरिक्त तरीकों प्रदान करता है -
threading.activeCount() - थ्रेड ऑब्जेक्ट्स की संख्या लौटाता है जो सक्रिय हैं।
threading.currentThread() - कॉलर के थ्रेड कंट्रोल में थ्रेड ऑब्जेक्ट की संख्या लौटाता है।
threading.enumerate() - वर्तमान में सक्रिय सभी थ्रेड ऑब्जेक्ट्स की सूची लौटाता है।
विधियों के अलावा, थ्रेडिंग मॉड्यूल में थ्रेड क्लास है जो थ्रेडिंग को लागू करता है। थ्रेड वर्ग द्वारा दिए गए तरीके निम्नानुसार हैं -
run() - रन () विधि एक थ्रेड के लिए प्रवेश बिंदु है।
start() - रन विधि को कॉल करके स्टार्ट () विधि एक धागा शुरू करती है।
join([time]) - द ज्वाइन () थ्रेड्स के समाप्त होने का इंतजार करता है।
isAlive() - isAlive () विधि यह जांचती है कि क्या कोई थ्रेड अभी भी निष्पादित हो रहा है।
getName() - getName () विधि एक थ्रेड का नाम देता है।
setName() - सेटनाम () विधि एक थ्रेड का नाम सेट करती है।
थ्रेडिंग मॉड्यूल का उपयोग करके थ्रेड बनाना
सूत्रण मॉड्यूल का उपयोग करके एक नया धागा लागू करने के लिए, आपको निम्नलिखित कार्य करने होंगे -
थ्रेड वर्ग के एक नए उपवर्ग को परिभाषित करें ।
अतिरिक्त तर्क जोड़ने के लिए __init __ (स्व [, args]) विधि को ओवरराइड करें ।
फिर, रन (स्वयं [, args]) विधि को लागू करने के लिए ओवरराइड करें कि थ्रेड शुरू होने पर क्या करना चाहिए।
एक बार जब आपने नया थ्रेड उपवर्ग बना लिया है, तो आप इसका एक उदाहरण बना सकते हैं और फिर प्रारंभ () को लागू करके एक नया धागा शुरू कर सकते हैं , जो बदले में रन () विधि को कॉल करता है ।
उदाहरण
#!/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 ("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
# Create new threads
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print ("Exiting Main Thread")
परिणाम
जब हम उपरोक्त कार्यक्रम चलाते हैं, तो यह निम्नलिखित परिणाम उत्पन्न करता है -
Starting Thread-1
Starting Thread-2
Thread-1: Fri Feb 19 10:00:21 2016
Thread-2: Fri Feb 19 10:00:22 2016
Thread-1: Fri Feb 19 10:00:22 2016
Thread-1: Fri Feb 19 10:00:23 2016
Thread-2: Fri Feb 19 10:00:24 2016
Thread-1: Fri Feb 19 10:00:24 2016
Thread-1: Fri Feb 19 10:00:25 2016
Exiting Thread-1
Thread-2: Fri Feb 19 10:00:26 2016
Thread-2: Fri Feb 19 10:00:28 2016
Thread-2: Fri Feb 19 10:00:30 2016
Exiting Thread-2
Exiting Main Thread
सूत्र सिंक्रनाइज़ करना
पायथन के साथ प्रदान किए गए थ्रेडिंग मॉड्यूल में एक सरल-से-लागू लॉकिंग तंत्र शामिल है जो आपको थ्रेड्स को सिंक्रनाइज़ करने की अनुमति देता है। लॉक () विधि को कॉल करके एक नया लॉक बनाया जाता है , जो नया लॉक लौटाता है।
नए लॉक ऑब्जेक्ट की अधिग्रहित (अवरुद्ध) विधि का उपयोग थ्रेड्स को सिंक्रोनाइज़ करने के लिए बाध्य करने के लिए किया जाता है। वैकल्पिक अवरुद्ध पैरामीटर आपको यह नियंत्रित करने में सक्षम करता है कि थ्रेड लॉक प्राप्त करने के लिए प्रतीक्षा करता है या नहीं।
यदि अवरुद्ध करना 0 पर सेट है, तो थ्रेड 0 प्राप्त होने पर तुरंत वापस आ जाता है यदि लॉक को अधिग्रहित नहीं किया जा सकता है और 1 के साथ यदि लॉक प्राप्त किया गया है। यदि अवरुद्ध करना 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 ("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: Fri Feb 19 10:04:14 2016
Thread-1: Fri Feb 19 10:04:15 2016
Thread-1: Fri Feb 19 10:04:16 2016
Thread-2: Fri Feb 19 10:04:18 2016
Thread-2: Fri Feb 19 10:04:20 2016
Thread-2: Fri Feb 19 10:04:22 2016
Exiting Main Thread
बहुविध प्राथमिकता कतार
कतार मॉड्यूल आप एक नया कतार उद्देश्य यह है कि आइटम की एक विशिष्ट संख्या धारण कर सकते हैं बनाने के लिए अनुमति देता है। कतार को नियंत्रित करने के लिए निम्नलिखित तरीके हैं -
get() - प्राप्त () कतार से एक आइटम को निकालता है और वापस करता है।
put() - पुट एक कतार में आइटम जोड़ता है।
qsize() - qsize () उन आइटमों की संख्या लौटाता है जो वर्तमान में कतार में हैं।
empty()- खाली () सही है अगर कतार खाली है; अन्यथा, गलत।
full()- पूर्ण () सही है अगर कतार भरी हुई है; अन्यथा, गलत।
उदाहरण
#!/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 ("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