Python多线程使用方法详细讲解
在 Python 中,多线程可以用于许多场景,比如爬虫、并行处理等。本文将详细讲解 Python 多线程的使用,包括线程创建、启动、停止、同步等方面。
线程创建
Python 中创建线程有两种方式:函数和类。我们先看函数方式的创建。
函数方式
在 Python 中,可以使用 threading
模块的 Thread()
方法来创建线程。Thread()
接受一个函数和一个参数,这个函数就是线程执行的代码,参数是传递给这个函数的参数,具体示例代码如下:
import threading
def say_hi(name):
print(f"Hi, {name}!")
thread = threading.Thread(target=say_hi, args=('San Zhang',))
thread.start()
在上面的代码中,我们创建了一个 say_hi()
函数,用于输出“Hi, XXX!” 的字符串。然后创建了一个 Thread
对象,由 say_hi()
函数作为线程执行的代码,args=('San Zhang',)
表示将 'San Zhang'
这个参数传递给 say_hi()
函数。最后启动线程,我们可以看到输出了 Hi, San Zhang!
的字符串。
类方式
在 Python 中,可以创建一个类,并继承 threading.Thread
类来创建线程。这个类需要覆写 run()
方法,run()
方法中就是线程执行的代码。具体示例代码如下:
import threading
class PrintingThread(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run(self):
for i in range(3):
print(f"{self.name}: {i}")
thread1 = PrintingThread('Thread 1')
thread2 = PrintingThread('Thread 2')
thread1.start()
thread2.start()
在上面的代码中,我们创建了一个 PrintingThread
类,并继承 threading.Thread
类。__init__()
方法中,我们通过 super()
调用父类的构造方法,将 name
作为参数传递给父类。然后,我们覆写了 run()
方法,用于打印 "name: i"
的字符串,其中 name
就是在 __init__()
方法中传递的参数。
然后,我们创建了两个 PrintingThread
对象,分别为 thread1
和 thread2
。最后,我们启动了这两个线程,我们可以看到输出了交替执行的 thread1
和 thread2
的输出结果。
线程同步
在多线程编程中,线程同步是很重要的一部分,如果多个线程同时访问某个共享资源,那么很可能会导致数据错误或者线程间死锁等问题。Python 中可以使用一些机制来保证线程同步,比如互斥锁、条件变量等。
互斥锁
在 Python 中,可以创建一个 Lock()
对象来实现线程同步。具体示例代码如下:
import threading
counter = 0
lock = threading.Lock()
class CounterThread(threading.Thread):
def run(self):
global counter, lock
for i in range(100000):
lock.acquire()
counter += 1
lock.release()
thread1 = CounterThread()
thread2 = CounterThread()
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print(counter)
在上面的代码中,我们创建了一个 Lock()
对象,称为 lock
。然后我们创建了一个 CounterThread
类,并覆写了 run()
方法。run()
方法中,我们在访问 counter
变量之前先获得锁(使用 acquire()
方法),并在修改完 counter
变量后释放锁(使用 release()
方法)。这样就保证了对 counter
变量的访问是互斥的。最后,我们创建了两个 CounterThread
对象,启动这两个线程,并等待线程执行完毕。最后,输出 counter
变量的值。
条件变量
在 Python 中,可以创建一个 Condition()
对象来实现线程同步。具体示例代码如下:
import threading
queue = []
cond = threading.Condition()
class ProducerThread(threading.Thread):
def run(self):
global queue, cond
for i in range(10):
cond.acquire()
queue.append(i)
print(f"Produced {i}")
cond.notify()
cond.release()
class ConsumerThread(threading.Thread):
def run(self):
global queue, cond
for i in range(10):
cond.acquire()
while not queue:
cond.wait()
item = queue.pop(0)
print(f"Consumed {item}")
cond.release()
producer = ProducerThread()
consumer = ConsumerThread()
producer.start()
consumer.start()
producer.join()
consumer.join()
在上面的代码中,我们创建了一个 Condition()
对象,称为 cond
。然后我们创建了一个 ProducerThread
类,并覆写了 run()
方法。run()
方法中,我们向 queue
列表中添加元素,并输出 "Produced i"
的字符串。然后调用 cond.notify()
方法唤醒等待在 cond
条件变量上的线程,并最后释放锁(使用 release()
方法)。
我们还创建了一个 ConsumerThread
类,并覆写了 run()
方法。run()
方法中,我们先获取锁(使用 acquire()
方法),然后判断 queue
是否为空。如果为空,就调用 cond.wait()
方法等待唤醒。如果不为空,就从 queue
列表中弹出第一个元素,输出 "Consumed i"
的字符串,并释放锁(使用 release()
方法)。
最后,我们创建了一个 ProducerThread
和一个 ConsumerThread
对象,启动这两个线程,并等待线程执行完毕。
线程停止
线程的停止可以使用 threading.Event()
来控制。 Event
是一个线程同步工具,一个线程调用 Event.wait()
方法会进入阻塞状态,直到另一个线程调用 Event.set()
方法为止。
具体示例代码如下:
import threading
stop_event = threading.Event()
class StoppableThread(threading.Thread):
def run(self):
global stop_event
i = 0
while not stop_event.is_set():
i += 1
print(i)
print("Stopped")
thread1 = StoppableThread()
thread2 = StoppableThread()
thread1.start()
thread2.start()
# 通过 Event 控制线程停止
stop_event.set()
thread1.join()
thread2.join()
在上面的代码中,我们创建了一个 Event()
对象,称为 stop_event
。然后我们创建了一个 StoppableThread
类,并覆写了 run()
方法。run()
方法中,我们使用了一个循环来输出数字,当 stop_event
的 is_set()
方法返回 True
的时候,就退出循环,并输出 "Stopped"
的字符串。最后,我们创建了两个 StoppableThread
对象,启动这两个线程,并等待一段时间后,通过 stop_event.set()
方法控制线程停止。
总结
本文详细讲解了 Python 多线程的使用方法,包括线程创建、启动、停止、同步等方面的内容。通过阅读本文,读者可以清楚地了解 Python 多线程编程的基础知识,并能够在实践中灵活运用。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python多线程使用方法详细讲解 - Python技术站