Python — многопоточное программирование
Предыдущая страницаСледующая страница
Запуск нескольких потоков аналогичен одновременному запуску нескольких разных программ, но со следующими преимуществами —
-
Несколько потоков внутри процесса совместно используют одно и то же пространство данных с основным потоком и поэтому могут обмениваться информацией или взаимодействовать друг с другом легче, чем если бы они были отдельными процессами.
-
Потоки иногда называют легковесными процессами, и они не требуют больших затрат памяти; они дешевле процессов.
Поток имеет начало, последовательность выполнения и завершение. У него есть указатель инструкций, который отслеживает, где в контексте он выполняется в данный момент.
-
Его можно прервать (прервать)
-
Его можно временно приостановить (также называется спящим), пока другие потоки работают — это называется уступкой.
Начало новой темы
Чтобы создать другой поток, вам нужно вызвать следующий метод, доступный в thread модуль —
thread.start_new_thread ( function, args[, kwargs] )
Этот вызов метода позволяет быстро и эффективно создавать новые потоки как в Linux, так и в Windows.
Вызов метода возвращается немедленно, и дочерний поток запускается и вызывает функцию с переданным списком аргументов. . Когда функция возвращается, поток завершается.
Здесь аргументы кортеж аргументов; используйте пустой кортеж для вызова функции без передачи каких-либо аргументов. кварги является необязательным словарем аргументов ключевого слова.
Пример
#!/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
Хотя это очень эффективно для низкоуровневых потоков, но thread модуль очень ограничен по сравнению с более новым модулем потоковой обработки.
Потоки Модуль
Более новый модуль потоков, включенный в Python 2.4, обеспечивает гораздо более мощную и высокоуровневую поддержку потоков, чем модуль потоков, рассмотренный в предыдущем разделе.
потоки модуль предоставляет все методы потока модуль и предоставляет некоторые дополнительные методы —
-
threading.activeCount() − Возвращает количество активных объектов потока.
-
threading.currentThread() − Возвращает количество объектов потока в элементе управления потоком вызывающей стороны.
-
threading.enumerate() − Возвращает список всех объектов потока, которые в данный момент активны.
В дополнение к методам модуль threading имеет Thread класс, реализующий многопоточность. Методы, предоставляемые Thread класс выглядит следующим образом —
-
выполнить() − Метод run() является точкой входа для потока.
-
начать() − Метод start() запускает поток, вызывая метод run.
-
присоединиться([время]) − Функция join() ожидает завершения потоков.
-
являетсяживым() − Метод isAlive() проверяет, выполняется ли еще поток.
-
получитьИмя() − Метод getName() возвращает имя потока.
-
установитьИмя() − Метод setName() устанавливает имя потока.
Создание темы с помощью Threading Модуль
Чтобы реализовать новый поток с помощью модуля потоковой передачи, вы должны сделать следующее —
-
Определите новый подкласс 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, поток блокируется и ожидает снятия блокировки.
релиз() метод нового объекта блокировки используется для снятия блокировки, когда она больше не требуется.
Пример
#!/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
Многопоточная приоритетная очередь
Очередь модуль позволяет создать новый объект очереди, который может содержать определенное количество элементов. Существуют следующие методы управления очередью —
-
получить() − get() удаляет и возвращает элемент из очереди.
-
вставить() − Помещение добавляет элемент в очередь.
-
qsize() − qsize() возвращает количество элементов, находящихся в данный момент в очереди.
-
пусто() − empty() возвращает True, если очередь пуста; в противном случае — False.
-
полный() − full() возвращает True, если очередь заполнена; в противном случае — False.
Пример
#!/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"
Когда приведенный выше код выполняется, он дает следующий результат —
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
- Нарезание резьбы и накатка резьбы:в чем разница?
- Типы данных Python
- Операторы Python
- Оператор передачи Python
- Аргументы функции Python
- Словарь Питона
- Объектно-ориентированное программирование Python
- Python — сетевое программирование
- Python — программирование расширений с помощью C
- Цикл резьбы Fanuc G76 для чайников