Python 3 -多线程编程
随着互联网的普及和计算机技术的不断发展,现在我们的电脑可以一边看视频,一边打游戏,同时还可以开着浏览器、文本编辑器等等。这就要归功于多线程技术。多线程是一种让计算机同时处理多个任务的技术,可以提高程序运行的效率,尤其是对于网络编程,因为可以同时处理多个网络请求,从而提高服务器的处理能力,降低用户等待的时长。Python 3提供了丰富的多线程编程方法,本文将介绍Python 3中的多线程编程,供读者学习和参考。
Python中的多线程模块
Python 3中提供了两种多线程模块:thread和threading,其中,thread模块已经被废弃,使用threading模块可以更好的进行多线程编程。
使用threading模块需要导入该模块,代码如下:
import threading
通过创建线程对象并启动线程,来运行多线程程序。创建线程对象的方法有两种:
- 通过继承Thread类创建线程
import threading
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 ("开始线程:" + self.name)
# 线程执行的代码
print ("退出线程:" + self.name)
# 创建新线程
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
# 开启新线程
thread1.start()
thread2.start()
print ("退出主线程")
- 通过直接调用Thread类的构造函数创建线程
import threading
def print_time(threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print ("%s: %s" % (threadName, time.ctime(time.time())))
# 创建新线程
thread1 = threading.Thread(target=print_time, args=("Thread-1", 1))
thread2 = threading.Thread(target=print_time, args=("Thread-2", 2))
# 开启新线程
thread1.start()
thread2.start()
print ("退出主线程")
多线程的基本操作
启动线程
在Python 3中,启动线程有两种方法:继承Thread类和直接创建Thread对象。使用Thread类方法时,只需要在创建线程对象时设定要执行的函数;而使用直接创建Thread对象的方法时,需要将要执行的函数作为target参数来传递。
import threading
# 定义执行的函数
def print_time(threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print ("%s: %s" % (threadName, time.ctime(time.time())))
# 使用继承Thread类方法创建线程
class MyThread (threading.Thread):
def __init__(self, threadID, name, counter, delay):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
self.delay = delay
def run(self):
print ("开始线程:" + self.name)
print_time(self.name, self.delay)
print ("退出线程:" + self.name)
# 创建新线程
thread1 = MyThread(1, "Thread-1", 1, 1)
thread2 = MyThread(2, "Thread-2", 2, 2)
# 开启新线程
thread1.start()
thread2.start()
print ("退出主线程")
线程同步
多线程编程中,线程之间会相互干扰,甚至导致数据错误,因此需要进行线程同步。Python 3中提供了Lock、RLock、Semaphore、Event等同步机制。
Lock
Lock类是最基本的同步原语,提供了多线程操作时的排他性。在需要使用共享资源的代码块中,程序可以调用acquire()方法获得锁,当程序执行完毕后,使用release()方法释放锁。
import threading
lock = threading.Lock()
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 ("开始线程:" + self.name)
# 获取锁
lock.acquire()
print_time(self.name, self.counter)
# 释放锁
lock.release()
print ("退出线程:" + self.name)
# 创建新线程
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
# 开启新线程
thread1.start()
thread2.start()
print ("退出主线程")
RLock
RLock类是可重入锁,即允许一个线程多次获取同一个锁,其方式与Lock类相同。
import threading
lock = threading.RLock()
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 ("开始线程:"+ self.name)
lock.acquire()
print_time(self.name, self.counter)
lock.release()
print ("退出线程:"+self.name)
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
thread1.start()
thread2.start()
print ("退出主线程")
Semaphore
Semaphore类是允许多个线程同时访问一定数量资源的同步机制,通常用于限制同时访问一个资源的线程数量。
import threading
semaphore = threading.Semaphore(2)
class MyThread (threading.Thread):
def __init__(self, threadID, name, delay):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.delay = delay
def run(self):
print ("开始线程:"+ self.name)
semaphore.acquire()
print_time(self.name, self.delay)
semaphore.release()
print ("退出线程:"+self.name)
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
thread3 = MyThread(3, "Thread-3", 3)
thread1.start()
thread2.start()
thread3.start()
print ("退出主线程")
Event
Event类用于线程之间的通信,一个线程通知另一个线程某个事件发生。一个线程可以等待事件,也可以重置事件。
import threading
event = threading.Event()
class MyThread (threading.Thread):
def __init__(self, threadID, name, delay):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.delay = delay
def run(self):
print ("开始线程:" + self.name)
# 等待事件
event.wait()
print_time(self.name, self.delay)
print ("退出线程:" + self.name)
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
thread1.start()
thread2.start()
time.sleep(2)
# 事件触发
event.set()
print ("退出主线程")
线程优先级
线程在执行时,可能会强制停止,转而执行其他线程的操作,这就是线程优先级。线程优先级在Python 3中可以设置,但是既使设置了优先级,也不能完全按照优先级执行,因为Python 3没有提供严格的优先级保证。
在Python 3中,线程的优先级有三个等级:LOWEST、LOW、NORMAL、HIGH、HIGHEST,使用threading模块中Thread类的set_priority()函数可以进行设置。默认情况下,所有线程都是NORMAL级别的。
import threading
class MyThread (threading.Thread):
def __init__(self, threadID, name, priority):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.priority = priority
def run(self):
print ("开始线程:" + self.name)
print_time(self.name, self.priority)
print ("退出线程:" + self.name)
thread1 = MyThread(1, "Thread-1", threading.ThreadPriority.HIGHEST)
thread2 = MyThread(2, "Thread-2", threading.ThreadPriority.LOW)
thread1.start()
thread2.start()
print ("退出主线程")
多线程的应用和注意事项
线程池
线程池是一种常见的线程管理方式,它可以控制线程数量的上限,并且重复利用已经创建的线程。线程池的优点在于减少线程的创建和销毁开销,同时提高程序的可伸缩性,降低程序的资源占用等。
在Python 3中,可以使用ThreadPoolExecutor 类来实现线程池,代码如下:
from concurrent.futures import ThreadPoolExecutor
import threading
def print_time(threadName, delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print ("%s: %s" % (threadName, time.ctime(time.time())))
# 创建线程池
threadPool = ThreadPoolExecutor(max_workers=2)
# 提交任务
future1 = threadPool.submit(print_time, "Thread-1", 1)
future2 = threadPool.submit(print_time, "Thread-2", 2)
# 等待任务完成
future1.result()
future2.result()
print ("退出主线程")
注意事项
- 多线程编程需要考虑线程的安全性和同步性,对临界资源进行保护,避免竞争条件的出现。
- 多线程编程需要考虑资源的分配,合理的分配线程,避免创建过多的线程导致资源的浪费。
- 多线程编程在处理I/O密集型任务中会遇到一些问题,如果线程的数量多了,很有可能会降低性能,使用协程的方式来解决这个问题。
结论
Python 3提供了多种多样的多线程编程方法,可以方便地实现多线程编程,提高程序的效率。本文介绍了Python 3中的多线程模块,以及多线程的基本操作、同步、优先级设置、线程池和注意事项。希望本文可以对Python 3多线程编程感兴趣的读者提供一些参考和帮助。