Запуск нескольких потоков аналогичен запуску нескольких различных программ одновременно, но со следующими преимуществами:
-
Несколько потоков внутри процесса совместно используют одно и то же пространство данных с основным потоком и поэтому могут обмениваться информацией или общаться друг с другом легче, чем если бы они были отдельными процессами.
-
Потоки иногда называют легкими процессами, и они не требуют больших затрат памяти; они дешевле, чем процессы.
Несколько потоков внутри процесса совместно используют одно и то же пространство данных с основным потоком и поэтому могут обмениваться информацией или общаться друг с другом легче, чем если бы они были отдельными процессами.
Потоки иногда называют легкими процессами, и они не требуют больших затрат памяти; они дешевле, чем процессы.
Поток имеет начало, последовательность выполнения и заключение. У него есть указатель инструкции, который отслеживает, где в его контексте он работает.
-
Это может быть прервано (прервано)
-
Он может быть временно приостановлен (также известный как спящий режим) во время работы других потоков — это называется уступкой.
Это может быть прервано (прервано)
Он может быть временно приостановлен (также известный как спящий режим) во время работы других потоков — это называется уступкой.
Начиная новую тему
Чтобы создать другой поток, вам нужно вызвать следующий метод, доступный в модуле потока —
thread.start_new_thread ( function, args[, kwargs] )
Этот вызов метода позволяет быстро и эффективно создавать новые потоки как в Linux, так и в Windows.
Вызов метода немедленно возвращается, и дочерний поток запускается и вызывает функцию с переданным списком аргументов . Когда функция возвращается, поток завершается.
Здесь args — это кортеж аргументов; используйте пустой кортеж для вызова функции без передачи аргументов. kwargs — это необязательный словарь аргументов ключевых слов.
пример
#!/usr/bin/python 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: 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
Хотя это очень эффективно для низкоуровневых потоков, но модуль потоков очень ограничен по сравнению с более новым модулем потоков.
Поточный модуль
Более новый модуль потоков, включенный в Python 2.4, обеспечивает гораздо более мощную высокоуровневую поддержку потоков, чем модуль потоков, рассмотренный в предыдущем разделе.
Модуль потоков предоставляет все методы модуля потоков и предоставляет некоторые дополнительные методы:
-
threading.activeCount () — возвращает количество активных объектов потока.
-
threading.currentThread () — возвращает количество объектов потока в элементе управления потока вызывающей стороны.
-
threading.enumerate () — возвращает список всех объектов потока, которые в данный момент активны.
threading.activeCount () — возвращает количество активных объектов потока.
threading.currentThread () — возвращает количество объектов потока в элементе управления потока вызывающей стороны.
threading.enumerate () — возвращает список всех объектов потока, которые в данный момент активны.
В дополнение к методам, у модуля потоков есть класс Thread, который реализует потоки. Методы, предоставляемые классом Thread , следующие:
-
run () — Метод run () является точкой входа для потока.
-
start () — метод start () запускает поток, вызывая метод run.
-
join ([время]) — join () ожидает завершения потоков.
-
isAlive () — метод isAlive () проверяет, выполняется ли еще поток.
-
getName () — Метод getName () возвращает имя потока.
-
setName () — Метод setName () устанавливает имя потока.
run () — Метод run () является точкой входа для потока.
start () — метод start () запускает поток, вызывая метод run.
join ([время]) — join () ожидает завершения потоков.
isAlive () — метод isAlive () проверяет, выполняется ли еще поток.
getName () — Метод getName () возвращает имя потока.
setName () — Метод setName () устанавливает имя потока.
Создание темы с использованием модуля Threading
Чтобы реализовать новый поток с помощью модуля потоков, вы должны сделать следующее:
-
Определите новый подкласс класса Thread .
-
Переопределите метод __init __ (self [, args]), чтобы добавить дополнительные аргументы.
-
Затем переопределите метод run (self [, args]), чтобы реализовать то, что поток должен делать при запуске.
Определите новый подкласс класса Thread .
Переопределите метод __init __ (self [, args]), чтобы добавить дополнительные аргументы.
Затем переопределите метод run (self [, args]), чтобы реализовать то, что поток должен делать при запуске.
Создав новый подкласс Thread , вы можете создать его экземпляр, а затем запустить новый поток, вызвав метод start () , который, в свою очередь, вызывает метод run () .
пример
#!/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 # Create new threads thread1 = myThread(1, "Thread-1", 1) thread2 = myThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() print "Exiting Main Thread"
Когда приведенный выше код выполняется, он дает следующий результат —
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
Синхронизация потоков
Модуль потоков, поставляемый с Python, включает в себя простой в реализации механизм блокировки, который позволяет синхронизировать потоки. Новая блокировка создается путем вызова метода Lock () , который возвращает новую блокировку.
Метод получения (блокирования) нового объекта блокировки используется для принудительной синхронной работы потоков. Необязательный параметр блокировки позволяет вам контролировать, ожидает ли поток получения блокировки.
Если для блокировки установлено значение 0, поток немедленно возвращает значение 0, если блокировка не может быть получена, и 1, если блокировка получена. Если для блокировки установлено значение 1, поток блокируется и ожидает снятия блокировки.
Метод release () нового объекта блокировки используется для снятия блокировки, когда она больше не требуется.
пример
#!/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 # 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: 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
Многопоточная приоритетная очередь
Модуль Queue позволяет вам создать новый объект очереди, который может содержать определенное количество элементов. Существуют следующие способы управления очередью:
-
get () — get () удаляет и возвращает элемент из очереди.
-
put () — Put добавляет элемент в очередь.
-
qsize () — qsize () возвращает количество элементов, которые в данный момент находятся в очереди.
-
empty () — empty () возвращает True, если очередь пуста; в противном случае Ложь.
-
full () — full () возвращает True, если очередь заполнена; в противном случае Ложь.
get () — get () удаляет и возвращает элемент из очереди.
put () — Put добавляет элемент в очередь.
qsize () — qsize () возвращает количество элементов, которые в данный момент находятся в очереди.
empty () — empty () возвращает True, если очередь пуста; в противном случае Ложь.
full () — full () возвращает True, если очередь заполнена; в противном случае Ложь.
пример
#!/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 # 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"
Когда приведенный выше код выполняется, он дает следующий результат —