Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> Python

Python Multithreaded Programmering: Efficiënte Concurrency Technieken

Het draaien van verschillende threads is vergelijkbaar met het draaien van verschillende programma's gelijktijdig, maar met de volgende voordelen:

  • Meerdere threads binnen een proces delen dezelfde dataspace met de main thread en kunnen daardoor informatie delen of met elkaar communiceren gemakkelijker dan als ze afzonderlijke processen waren.

  • Threads worden soms lichtgewicht processen genoemd en ze vereisen niet veel geheugenoverhead; ze zijn goedkoper dan processen.

Een thread heeft een begin, een uitvoeringsequentie en een conclusie. Het heeft een instructiepointer die bijhoudt waar binnen zijn context het momenteel draait.

  • Het kan pre-empted (onderbroken) worden

  • Het tijdelijk op hold gezet worden (ook wel slapen genoemd) terwijl andere threads draaien - dit heet yielding.

Een Nieuwe Thread Starten

Om een andere thread te spawnen, moet u de volgende methode aanroepen die beschikbaar is in de thread-module:

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

Deze methodcall stelt een snelle en efficiënte manier in om nieuwe threads aan te maken in zowel Linux als Windows.

De methodcall retourneert onmiddellijk en de child thread start en roept de functie aan met de doorgegeven lijst van args. Wanneer de functie retourneert, termineert de thread.

Hier is args een tuple van argumenten; gebruik een lege tuple om de functie aan te roepen zonder argumenten door te geven. kwargs is een optionele dictionary van keyword-argumenten.

Voorbeeld

#!/usr/bin/python
import thread
import time

# Een functie voor de thread definiëren
def print_time(threadName, delay):
    count = 0
    while count < 5:
        time.sleep(delay)
        count += 1
        print "%s: %s" % (threadName, time.ctime(time.time()))

# Twee threads aanmaken als volgt
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

Wanneer de bovenstaande code wordt uitgevoerd, produceert het het volgende resultaat:

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

Hoewel het heel effectief is voor low-level threading, is de thread-module heel beperkt vergeleken met de nieuwere threading-module.

De Threading-Module

De nieuwere threading-module die bij Python 2.4 wordt meegeleverd, biedt veel krachtigere, high-level ondersteuning voor threads dan de thread-module die in de vorige sectie besproken werd.

De threading-module blootstelt alle methodes van de thread-module en biedt enkele extra methodes:

  • threading.activeCount() - Retourneert het aantal thread-objecten dat actief is.

  • threading.currentThread() - Retourneert het aantal thread-objecten in de thread-control van de aanroeper.

  • threading.enumerate() - Retourneert een lijst van alle thread-objecten die momenteel actief zijn.

Naast de methodes heeft de threading-module de Thread-klasse die threading implementeert. De methodes die door de Thread-klasse worden geboden, zijn als volgt:

  • run() - De run()-methode is het startpunt voor een thread.

  • start() - De start()-methode start een thread door de run-methode aan te roepen.

  • join([time]) - De join()-methode wacht tot threads beëindigd zijn.

  • isAlive() - De isAlive()-methode controleert of een thread nog steeds uitvoert.

  • getName() - De getName()-methode retourneert de naam van een thread.

  • setName() - De setName()-methode stelt de naam van een thread in.

Thread Maken met Threading-Module

Om een nieuwe thread te implementeren met de threading-module, moet u het volgende doen:

  • Definieer een nieuwe subklasse van de Thread-klasse.

  • Override de __init__(self[, args])-methode om extra argumenten toe te voegen.

  • Vervolgens override de run(self[, args])-methode om te implementeren wat de thread moet doen wanneer gestart.

Eenmaal u de nieuwe Thread-subklasse hebt gemaakt, kunt u een instantie ervan aanmaken en vervolgens een nieuwe thread starten door start() aan te roepen, wat op zijn beurt run() aanroept.

Voorbeeld

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

# Nieuwe threads aanmaken
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# Nieuwe Threads starten
thread1.start()
thread2.start()

print "Exiting Main Thread"

Wanneer de bovenstaande code wordt uitgevoerd, produceert het het volgende resultaat:

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

Threads Synchroniseren

De threading-module die met Python wordt meegeleverd, bevat een eenvoudig-te-implementeren vergrendelingsmechanisme dat u in staat stelt threads te synchroniseren. Een nieuwe lock wordt aangemaakt door de Lock()-methode aan te roepen, die de nieuwe lock retourneert.

De acquire(blocking)-methode van het nieuwe lock-object wordt gebruikt om threads gedwongen synchroon te laten draaien. De optionele blocking-parameter stelt u in staat te controleren of de thread wacht om de lock te verkrijgen.

Als blocking op 0 gezet is, retourneert de thread onmiddellijk met een 0-waarde als de lock niet verkregen kan worden en met een 1 als de lock verkregen was. Als blocking op 1 gezet is, blokkeert de thread en wacht tot de lock vrijgegeven wordt.

De release()-methode van het nieuwe lock-object wordt gebruikt om de lock vrij te geven wanneer deze niet meer nodig is.

Voorbeeld

#!/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
        # Lock verkrijgen om threads te synchroniseren
        threadLock.acquire()
        print_time(self.name, self.counter, 3)
        # Lock vrijgeven om volgende thread vrij te geven
        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 = []

# Nieuwe threads aanmaken
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# Nieuwe Threads starten
thread1.start()
thread2.start()

# Threads toevoegen aan thread-lijst
threads.append(thread1)
threads.append(thread2)

# Wachten tot alle threads voltooid zijn
for t in threads:
    t.join()

print "Exiting Main Thread"

Wanneer de bovenstaande code wordt uitgevoerd, produceert het het volgende resultaat:

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

De Queue-module stelt u in staat een nieuw queue-object aan te maken dat een specifiek aantal items kan bevatten. Er zijn de volgende methodes om de Queue te controleren:

  • get() - De get() verwijdert en retourneert een item uit de queue.

  • put() - De put voegt een item toe aan een queue.

  • qsize() - De qsize() retourneert het aantal items dat momenteel in de queue zit.

  • empty() - De empty() retourneert True als queue leeg is; anders False.

  • full() - De full() retourneert True als queue vol is; anders False.

Voorbeeld

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

# Nieuwe threads aanmaken
for tName in threadList:
    thread = myThread(threadID, tName, workQueue)
    thread.start()
    threads.append(thread)
    threadID += 1

# De queue vullen
queueLock.acquire()
for word in nameList:
    workQueue.put(word)
queueLock.release()

# Wachten tot queue leeg is
while not workQueue.empty():
    pass

# Threads melden dat het tijd is om te stoppen
exitFlag = 1

# Wachten tot alle threads voltooid zijn
for t in threads:
    t.join()

print "Exiting Main Thread"

Wanneer de bovenstaande code wordt uitgevoerd, produceert het het volgende resultaat:

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

Python

  1. Fanuc G76 Draadcyclus Beheersen: Complete Gids voor CNC-draaiers
  2. Gewindevormen vs Gewinderollen: de belangrijkste verschillen begrepen
  3. Python Datatypes onder de knie krijgen: Een praktische gids
  4. Python Operators onder de knie krijgen: Een uitgebreide gids
  5. Python's While Loop onder de knie krijgen: Syntaxis, Voorbeelden en Best Practices
  6. Python Pass Statement onder de knie krijgen: Een praktische gids
  7. Python Functie-argumenten onder de knie krijgen: Positionele, Keyword en Default Parameters
  8. Python-dictionaries beheersen: aanmaken, manipuleren en geavanceerde technieken
  9. Python Object-Oriented Programming beheersen: classes, inheritance, encapsulatie & polymorfisme
  10. Python Netwerkprogrammering: Sockets & Geavanceerde Protocols onder de knie
  11. Python Extensieprogrammering met C: Snelle, Native Modules Bouwen