如何在Python中使用线程进行编程
在软件开发中,线程是执行流的一种。一个进程可以有多个线程同时执行,每个线程独立执行,并且有自己的栈和寄存器等。线程是可以并发执行的,每个线程都是独立的,因此可以提高程序的运行效率。在Python中,线程模块是一个重要的组成部分,它为我们提供了多个线程的支持。本文将讨论如何使用Python来实现线程。
Python的线程特性
在Python中,有两个模块可以用于线程编程,分别为_thread
(低层次模块)和threading
(高层次模块)。
_thread
模块提供了多线程编程的基本支持,是一个低层次模块。使用该模块,可以创建,启动和终止线程。这个模块中的方法在Python 3中已经更名为_thread
。使用该模块来进行多线程编程,需要创建线程函数并且调用start_new_thread
方法。
而threading
模块对_thread
模块进行了封装,提供了一个更加高级的多线程编程接口。最大的不同是,可以创建Thread
对象并控制线程的状态。
使用_thread模块实现线程
在Python 3以前的版本,我们需要使用_thread
模块。在Python中,每个线程都是独立的,并且有自己独立的线程栈。我们可以通过以下代码来实现多线程:
import _thread
import time
import threading
#使用_thread模块实现线程
def thread_function(thread_name,delay):
count=0
while(count<5):
time.sleep(delay)
count+=1
print(thread_name+'执行,已执行'+str(count)+'次')
#开启三个线程
try:
_thread.start_new_thread(thread_function,('线程1',1))
_thread.start_new_thread(thread_function,('线程2',2))
_thread.start_new_thread(thread_function,('线程3',3))
except Exception as e:
print(e)
#等待所有线程执行结束
while True:
pass
在以上代码中:
_thread.start_new_thread()
方法用于开启新线程,并执行指定的函数;threading.Thread()
类用于创建线程对象;time.sleep()
方法用于让线程暂停一段时间;
当执行该代码时,会启动3个线程并并行执行。每个线程都会执行thread_function
函数,并在指定的时间间隔内打印一行带有线程名称和执行次数的语句。
需要注意的是,如果我们在try
中调用_thread.start_new_thread
方法时发生了异常,我们会在except
代码块中捕获该异常。否则,我们将陷入死循环,因为没有办法终止线程,直到它们完成。
利用threading
模块实现线程
threading
模块比_thread
模块提供了更加高级的线程编程接口。threading
模块提供了Thread
类,可以使用该类来创建线程对象并控制线程状态。下面是使用threading
模块实现线程的代码:
import threading
import time
class MyThread(threading.Thread):
def __init__(self, threadID, name, delay):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.delay = delay
self.count = 0
def run(self):
print ("开始线程:" + self.name)
while self.count < 5:
time.sleep(self.delay)
self.count += 1
print ("%s执行,已执行%s次" % (self.name, str(self.count)))
print ("结束线程:" + self.name)
# 创建线程
thread1 = MyThread(1, "线程1", 1)
thread2 = MyThread(2, "线程2", 2)
thread3 = MyThread(3, "线程3", 3)
# 开启线程
thread1.start()
thread2.start()
thread3.start()
# 等待线程结束
thread1.join()
thread2.join()
thread3.join()
print ("退出主线程")
在以上代码中,我们定义了MyThread
类,该类继承了threading.Thread
类。在类中,我们定义了构造函数和run
方法。构造函数用于初始化线程对象,并为线程指定ID、名称和延迟时间。run
方法是线程要执行的代码。
其中,我们使用了time.sleep()
方法来让线程在指定的时间内暂停,并通过计数器来控制线程的循环次数。当计数器达到5时,线程就会结束。
在主线程中,我们创建了3个线程对象,并通过调用start()
方法来开启线程。为了等待线程结束,我们使用了join()
方法。最后,我们在主线程中输出了一条消息。
线程锁
在线程编程中,由于多个线程同时访问共享资源,我们经常需要使用线程锁来保证线程安全。Python提供了_thread
和threading
两个模块的锁。下面是一个使用threading
模块的锁实例:
import threading
# 共享资源
num = 0
# 创建锁
lock = threading.Lock()
def add_number():
global num
# 获取锁
lock.acquire()
try:
# 修改共享资源
num += 1
finally:
# 释放锁
lock.release()
class MyThread(threading.Thread):
def run(self):
for i in range(100000):
add_number()
# 创建线程
thread1 = MyThread()
thread2 = MyThread()
# 开启线程
thread1.start()
thread2.start()
# 等待线程结束
thread1.join()
thread2.join()
# 输出结果
print(num)
在以上代码中,我们创建了一个全局变量num
,它将被多个线程访问。我们使用了threading.Lock()
类来创建一个锁对象。
在add_number()
函数中,我们获得了锁对象,并修改了共享资源num
的值。最后,我们释放了锁。
在MyThread
类中,我们重写了run()
方法,该方法循环调用add_number()
函数,并对num
变量进行累加操作。
在主线程中,我们创建了两个线程对象,并启动了这两个线程。最后,我们输出了num
的值。
结论
Python提供了两个模块来支持线程编程——_thread
和threading
。_thread
是一个低级的模块,提供了基本的多线程支持。threading
则是对_thread
模块的高级封装,提供了更加简单和易用的编程接口。
在多线程编程时,我们需要注意线程安全问题。由于多个线程同时访问同一个共享资源,很容易导致数据竞争和死锁等问题。因此,我们需要使用线程锁来保证线程安全。
最后,我们需要注意的是,多线程编程不是银弹。在设计多线程程序时,需要仔细分析多线程的利弊,并权衡利弊,从而得出更好的设计方案。