python主要是通过thread和threading这两个模块来实现多线程支持
1,thread模块是比较底层的模块,thread 模块提供了低级别的基本功能来支持多线程功能,提供简单的锁来确保同步,推荐使用 threading 模块。
2,threading模块是对thread做了一些封装 (但是python由于GIL(global interpreter lock 全局解释锁)的存在无法使用threading充分利用CPU资源,GIL使得python同一个时刻只有一个线程在一个cpu上执行字节码,并且无法将多个线程映射到多个cpu上,即不能发挥多个cpu的优势。即多线程只能在一个CPU上执行,CPU是按照时间片轮询的方式来执行子线程的,如果想充分发挥多核CPU的计算能力需要使用multiprocessing模块(Windows下使用会有诸多问题)
1.使用threading创建多线程
方法一:是创建 threading.Thread 实例,调用其 start() 方法
import time
import threading
def task_thread(counter):
print(f'线程名称:{threading.current_thread().name} 参数:{counter} 开始时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
num = counter
while num:
time.sleep(3)
num -= 1
print(f'线程名称:{threading.current_thread().name} 参数:{counter} 结束时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
if __name__ == '__main__':
print(f'主线程开始时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
#初始化3个线程,传递不同的参数
t1 = threading.Thread(target=task_thread, args=(3,))
t2 = threading.Thread(target=task_thread, args=(2,))
t3 = threading.Thread(target=task_thread, args=(1,))
#开启三个线程
t1.start()
t2.start()
t3.start()
#等待运行结束
t1.join()
t2.join()
t3.join()
print(f'主线程结束时间:{time.strftime("%Y-%m-%d %H:%M:%S")}')
方法二:继承 Thread 类,在子类中重写 run() 和 init() 方法
import threading
import time
class myThread(threading.Thread):
# 继承父类threading.Thread
def __init__(self, threadID, name, counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self): # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
print("Starting " + self.name)
print_time(self.name, self.counter, 5)
print("Exiting " + self.name)
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print("%s process at: %s" % (threadName, time.ctime(time.time())))
counter -= 1
if __name__ == '__main__':
# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)
# 开启线程
thread1.start()
thread2.start()
# 等待线程结束
thread1.join()
thread2.join()
print("Exiting Main Thread")
线程同步:
Lock(互斥锁)
实现方法:
acquire(): 尝试获得锁定。使线程进入同步阻塞状态。
release(): 释放锁。使用前线程必须已获得锁定,否则将抛出异常。
Semaphore(信号量)
互斥锁同时只允许一个线程访问共享数据,而信号量是同时允许一定数量的线程访问共享数据,
semaphore = threading.BoundedSemaphore(5) #允许5个线程获取锁
semaphore.acquire() #获取锁
semaphore.release() #释放锁
Condition(条件)
条件对象能让一个线程 A 停下来,等待其他线程 B ,线程 B 满足了某个条件后通知(notify)线程 A 继续运行。线程首先获取一个条件变量锁,如果条件不足,则该线程等待(wait)并释放条件变量锁,如果满足就执行线程,也可以通知其他状态为 wait 的线程。
Event(事件)
事件用于线程间通信。一个线程发出一个信号,其他一个或多个线程等待,调用 event 对象的 wait 方法,线程则会阻塞等待,直到别的线程 set 之后,才会被唤醒。
Queue(队列)
Python 的 queue 模块中提供了同步的、线程安全的队列类,包括先进先出队列 Queue,后进先出队列 LifoQueue,和优先级队列 PriorityQueue。这些队列都实现了锁原语,可以直接使用来实现线程间的同步。