Python的thread模块(在新版本中已被_thread
替代)可以通过创建一个线程实例并传入一个可调用的对象来创建线程。在更常用的threading
模块中,通常通过继承threading.Thread
类并重写其run
方法来创建线程,或者是通过实例化一个Thread
对象并传入一个函数和参数来作为线程执行的目标。下面我们将详细探讨这些方法并强调如何正确地使用它们,在创建线程时要注意的同步和状态管理问题。
一、使用_THREAD模块创建线程
_thread
模块提供的是较为底层和原始的线程操作。启动线程的基本方式是调用_thread.start_new_thread(function, args)
,其中function
是将在新线程中运行的函数,而args
是一个元组,用于传递参数。
import _thread
import time
线程要执行的函数
def print_time(threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print(f"{threadName}: {time.ctime(time.time())}")
创建两个线程
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 True:
pass
在这段代码中,我们创建了两个线程,它们各自输出当前时间但等待的秒数不同。
二、使用THREADING模块创建线程
threading
模块则提供了一个更高级别、更易用的API来进行线程操作。使用threading
模块,你可以很容易地创建和管理线程。
通过函数创建线程的方式是这样的:
import threading
import time
线程要执行的函数
def print_time(threadName, delay):
counter = 0
while counter < 5:
time.sleep(delay)
print(f"{threadName}: {time.ctime(time.time())}")
counter += 1
创建线程
thread1 = threading.Thread(target=print_time, args=("Thread-1", 2))
thread2 = threading.Thread(target=print_time, args=("Thread-2", 4))
开启线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("Exit MAIn Thread")
通过继承Thread类创建线程的方式则如下:
import threading
import time
class MyThread(threading.Thread):
def __init__(self, threadName, delay):
threading.Thread.__init__(self)
self.threadName = threadName
self.delay = delay
def run(self):
print(f"Starting {self.threadName}")
print_time(self.threadName, self.delay)
print(f"Exiting {self.threadName}")
def print_time(threadName, delay):
counter = 0
while counter < 5:
time.sleep(delay)
print(f"{threadName}: {time.ctime(time.time())}")
counter += 1
创建新线程
thread1 = MyThread("Thread-1", 2)
thread2 = MyThread("Thread-2", 4)
开启新线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("Exit Main Thread")
三、线程间的同步
在多线程环境中,同步是一个重要的概念。为了防止多个线程同时访问某个数据而造成混乱,可以使用线程同步机制来保持数据的一致性。
import threading
假定这是你的银行存款:
balance = 0
lock = threading.Lock()
def change_it(n):
global balance
balance = balance + n
balance = balance - n
def run_thread(n):
for i in range(100000):
# 先要获取锁:
lock.acquire()
try:
# 放心地改吧:
change_it(n)
finally:
# 改完了一定要释放锁:
lock.release()
t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)
在这段代码中,lock
对象被用来确保同一时刻只有一个线程能进行修改balance
操作。这样可以保证balance
在多线程中的正确性。
四、线程的状态管理
管理线程的状态意味着在运行时控制线程的执行、暂停、停止或其他状态的转换。在Python中主要通过设置线程内部的状态标志或使用threading
模块提供的同步原语来实现。
import threading
import time
class StoppableThread(threading.Thread):
def __init__(self):
super(StoppableThread, self).__init__()
self._stop_event = threading.Event()
def stop(self):
self._stop_event.set()
def run(self):
while not self._stop_event.is_set():
print('Thread is running...')
time.sleep(1)
print('Thread stopped')
thread = StoppableThread()
thread.start()
time.sleep(5)
thread.stop()
在这个例子中,我们定义了一个StoppableThread
类,线程可以根据内部的停止事件_stop_event
来判断何时停止执行。
总结起来,Python通过threading
和_thread
模块提供了创建和管理线程的强大功能。正确使用这些功能对于编写高效、稳定、易于维护的并发程序至关重要。
相关问答FAQs:
如何使用 Python thread 模块创建线程?
创建线程的步骤如下:
-
导入 thread 模块:在 Python 中,我们可以使用
import thread
来导入 thread 模块。 -
定义线程的函数:在创建一个线程之前,需要定义一个函数,这个函数将作为线程的入口点,即线程开始执行的地方。
-
创建线程对象:使用
thread.start_new_thread()
函数可以创建一个新的线程对象。此函数接受两个参数:线程的函数和一个元组参数,这个元组参数被传递给线程的函数作为参数。 -
启动线程:通过调用创建的线程对象的
start()
方法来启动线程。
下面是一个例子:
import thread
import time
# 定义线程的函数
def print_time(threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print("%s: %s" % (threadName, time.ctime(time.time())))
# 创建线程
try:
thread.start_new_thread(print_time, ("Thread-1", 2,))
thread.start_new_thread(print_time, ("Thread-2", 4,))
except:
print("Error: 无法启动线程")
while 1:
pass
如何在 Python 中启动多个线程?
在 Python 中可以使用 thread 模块的 start_new_thread()
函数来启动多个线程。每次调用 start_new_thread()
函数都会创建一个新的线程,并且可以指定线程的函数和参数。
例如,想要启动三个线程:
import thread
# 定义线程的函数
def my_thread(threadName):
print("Thread %s is running" % threadName)
# 启动线程
thread.start_new_thread(my_thread, ("Thread-1",))
thread.start_new_thread(my_thread, ("Thread-2",))
thread.start_new_thread(my_thread, ("Thread-3",))
while 1:
pass
每个线程都会执行相同的函数 my_thread()
,并且可以传递不同的参数。
如何在 Python 中控制线程的执行顺序?
在 Python 中,无法直接控制线程的执行顺序,因为线程是并发执行的,操作系统会根据调度算法来决定线程的执行顺序。但是可以使用一些技巧来实现线程之间的同步和协调。
一种常见的方法是使用锁(Lock)来实现线程的同步。通过在关键部分添加锁,只允许一个线程访问共享资源,其他线程需要等待锁的释放才能继续执行。
另一种方法是使用线程间的通信机制,例如信号量(Semaphore)、条件变量(Condition)或事件(Event)。通过这些机制,可以实现线程之间的等待、通知和唤醒操作,从而实现线程的协调与同步。
代码示例:
import thread
import time
# 定义线程的函数
def print_number(threadName, delay, lock):
count = 0
while count < 5:
# 加锁
lock.acquire()
print("%s: %d" % (threadName, count))
count += 1
# 释放锁
lock.release()
time.sleep(delay)
# 创建锁对象
lock = thread.allocate_lock()
# 创建线程
try:
thread.start_new_thread(print_number, ("Thread-1", 1, lock))
thread.start_new_thread(print_number, ("Thread-2", 2, lock))
except:
print("Error: 无法启动线程")
while 1:
pass
在上面的示例中,使用了锁来控制线程的执行顺序,每个线程在访问共享资源时需要获取锁,保证每次只有一个线程输出数字。