线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制
每个线程都有一组 CPU 寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的 CPU 寄存器的状态
什么是多线程
线程可以分为:
- 内核线程:由操作系统内核创建和撤销。
- 用户线程:不需要内核支持而在用户程序中实现的线程
调用_thread模块中的start_new_thread()函数产生新线程
为了兼容性,Python3 将 thread 重命名为 “_thread”
不推荐
导入:import _thread
_thread.start_new_thread(function, args[, kwargs])
- function:线程函数。
- args:传递给线程函数的参数,必须是tuple类型。
import _thread
import time
def print_time(threadName, delay):
count = 0
while count < 6:
time.sleep(delay)
count += 1
print(f"{threadName}:{time.ctime(time.time())}")
try:
_thread.start_new_thread(print_time, ("线程一", 2))
_thread.start_new_thread(print_time, ("线程二", 4))
except:
print('无法启动线程')
while 1:
pass
结果:
线程一:Thu Jul 21 12:07:48 2022 线程二:Thu Jul 21 12:07:50 2022 线程一:Thu Jul 21 12:07:50 2022 线程一:Thu Jul 21 12:07:52 2022 线程二:Thu Jul 21 12:07:54 2022 线程一:Thu Jul 21 12:07:54 2022 线程一:Thu Jul 21 12:07:56 2022 线程二:Thu Jul 21 12:07:58 2022 线程一:Thu Jul 21 12:07:58 2022 线程二:Thu Jul 21 12:08:02 2022 ...2、通过threading创建Thread类,自定义类继承Thread类
threading模块包含了_thread模块中所有方法
导入: import threading
除了_thread模块中的方法,还提供其他方法:
- threading.currentThread() 返回当前线程变量
- threading.enumerate() 返回正在运行的线程list
- threading.activeCount() 返回正在运行的线程数量
Thread类:Thread(target=方法名[, args=(参数1,参数2,...)])
- target 指要执行的任务,通常是方法名
- args 指执行任务需要传入的参数,元组形式
Thread类中方法:
- run() 表示线程活动方法
- start() 启动线程
- join([time]) 等待至线程中止
- isAlive() 返回线程是否活动
- getName() 返回线程名
- setName() 设置线程名
使用 threading 模块创建线程
通过直接从 threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程,即它调用了线程的 run() 方法
import threading
import time
# 继承Thread类
class MyThread(threading.Thread):
def __init__(self, name, delay):
threading.Thread.__init__(self)
self.name = name
self.delay = delay
def run(self):
print('开始线程:', self.name)
print_time(self.name, self.delay, 5)
print('结束线程:', self.name)
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print(f"{threadName}:{time.ctime(time.time())}")
counter -= 1
# 创建线程
thread1 = MyThread("线程一", 1)
thread2 = MyThread("线程二", 2)
# 开启线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print('退出线程')
结果:
开始线程: 线程一 开始线程: 线程二 线程一:Thu Jul 21 12:06:24 2022 线程二:Thu Jul 21 12:06:25 2022 线程一:Thu Jul 21 12:06:25 2022 线程一:Thu Jul 21 12:06:26 2022 线程二:Thu Jul 21 12:06:27 2022 线程一:Thu Jul 21 12:06:27 2022 线程一:Thu Jul 21 12:06:28 2022 结束线程: 线程一 线程二:Thu Jul 21 12:06:29 2022 线程二:Thu Jul 21 12:06:31 2022 线程二:Thu Jul 21 12:06:33 2022 结束线程: 线程二 退出线程线程同步
多线程的优势在于可以同时运行多个任务。但是当线程需要共享数据时,可能存在数据不同步的问题
解决资源共享问题,加入锁
锁有两种状态:锁定和未锁定
- 某个线程操作共享数据时必须先获得锁,其他线程必须等待上一个线程释放锁后,否则同步阻塞
使用threading模块的Lock和Rlock可实现简单线程同步,这两个对象都有acquire方法和release方法,共享数据的操作放在两个方法之间处理
import threading
import time
# 线程类
class MyThread(threading.Thread):
def __init__(self, name, delay):
threading.Thread.__init__(self)
self.name = name
self.delay = delay
def run(self):
print("start thread:", self.name)
# 获取锁
threadLock.acquire()
print_time(self.name, self.delay, 5)
# 释放锁
threadLock.release()
print("end thread:", self.name)
def print_time(threadName, delay, counter):
while counter:
time.sleep(delay)
print(f"{threadName}: {time.ctime(time.time())}")
counter -= 1
# 线程锁对象
threadLock = threading.Lock()
# 创建线程
thread1 = MyThread('thread-1', 1)
thread2 = MyThread('thread-2', 2)
# 开启线程
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print('退出主线程')
结果:
start thread: thread-1 start thread: thread-2 thread-1: Thu Jul 21 14:58:37 2022 thread-1: Thu Jul 21 14:58:38 2022 thread-1: Thu Jul 21 14:58:39 2022 thread-1: Thu Jul 21 14:58:40 2022 thread-1: Thu Jul 21 14:58:41 2022 end thread: thread-1 thread-2: Thu Jul 21 14:58:43 2022 thread-2: Thu Jul 21 14:58:45 2022 thread-2: Thu Jul 21 14:58:47 2022 thread-2: Thu Jul 21 14:58:49 2022 thread-2: Thu Jul 21 14:58:51 2022 end thread: thread-2 退出主线程Queue
Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列 PriorityQueue
常用方法:
| 方法 | 描述 |
|---|---|
| qsize() | 返回队列的大小 |
| empty() | 是否为空 |
| full() | 是否满对列 |
| get([block[, timeout]]) | 获取队列,timeout为等待时间 |
| get_nowait() | 相当于queue.get(False) |
| put(item) | 写入队列,timeout为等待时间 |
| put_nowait() | 相当于queue.put(item, False) |
| task_done() | 完成任务后向完成的队列发送信号 |
| join() | 等待队列为空时,执行其他操作 |
import queue
import threading
import time
# 线程类
class MyThread(threading.Thread):
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name
def run(self):
print("start thread:", self.name)
process_data(self.name)
print("end thread:", self.name)
exit = 0
def process_data(threadName):
while not exit:
# 获取锁
queueLock.acquire()
if not workQueue.empty():
data = workQueue.get()
queueLock.release()
print(f"{threadName} 获取 {data}")
else:
queueLock.release()
time.sleep(1)
# 线程锁对象
queueLock = threading.Lock()
# 构建大小为10的队列
workQueue = queue.Queue(10)
# 创建线程
thread1 = MyThread('thread-1')
thread2 = MyThread('thread-2')
# 开启线程
thread1.start()
thread2.start()
# 填充队列
queueLock.acquire()
for i in range(1, 6):
print(f'填充队列item{i}')
workQueue.put(f"队列item{i}")
queueLock.release()
# 等待队列清空
while not workQueue.empty():
pass
exit = 1
# 等待线程完成
thread1.join()
thread2.join()
print('退出主线程')
结果:
start thread: thread-1 start thread: thread-2 填充队列item1 填充队列item2 填充队列item3 填充队列item4 填充队列item5 thread-1 获取 队列item1 thread-2 获取 队列item2 thread-2 获取 队列item3 thread-1 获取 队列item4 thread-1 获取 队列item5 end thread: thread-1 end thread: thread-2 退出主线程



