包含编程籽料、学习路线图、爬虫代码、安装包等!【点击领取】
1. 线程基础概念
1.1 什么是线程?
线程(Thread)是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。一个进程可以包含多个线程,这些线程共享进程的内存空间。
1.2 Python中的线程实现
Python通过threading模块提供线程支持。需要注意的是,由于GIL(全局解释器锁)的存在,Python的多线程在CPU密集型任务上性能提升有限,但在I/O密集型任务中仍能显著提高程序效率。
2. 线程的基本使用
2.1 创建线程
Python中创建线程有两种主要方式:
方法一:使用Thread类直接创建
import threading
def worker():
print("线程执行中...")
print(f"当前线程: {threading.current_thread().name}")
# 创建线程
t = threading.Thread(target=worker, name="工作线程")
t.start()
t.join() # 等待线程结束
print("主线程结束")
方法二:继承Thread类
class MyThread(threading.Thread):
def __init__(self, name):
super().__init__()
self.name = name
def run(self):
print(f"{self.name}线程执行中...")
print(f"当前线程ID: {threading.get_ident()}")
t = MyThread("自定义")
t.start()
t.join()
2.2 线程常用方法
3. 线程同步与通信
3.1 锁(Lock)
import threading
counter = 0
lock = threading.Lock()
def increment():
global counter
for _ in range(100000):
with lock: # 自动获取和释放锁
counter += 1
threads = []
for i in range(5):
t = threading.Thread(target=increment)
threads.append(t)
t.start()
for t in threads:
t.join()
print(f"最终计数器值: {counter}") # 正确输出500000
3.2 条件变量(Condition)
import threading
import time
condition = threading.Condition()
items = []
def consumer():
with condition:
while not items:
condition.wait() # 等待通知
print(f"消费: {items.pop(0)}")
def producer():
with condition:
items.append(1)
condition.notify() # 通知等待的线程
t1 = threading.Thread(target=consumer)
t2 = threading.Thread(target=producer)
t1.start()
time.sleep(1) # 确保consumer先执行
t2.start()
t1.join()
t2.join()
3.3 信号量(Semaphore)
import threading
import time
semaphore = threading.Semaphore(3) # 最多允许3个线程同时访问
def access_resource(thread_id):
with semaphore:
print(f"线程{thread_id}正在访问资源")
time.sleep(2)
print(f"线程{thread_id}释放资源")
threads = []
for i in range(10):
t = threading.Thread(target=access_resource, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
4. 线程池的使用
Python 3.2+引入了concurrent.futures模块,提供了更高级的线程池接口:
from concurrent.futures import ThreadPoolExecutor
import time
def task(n):
print(f"处理任务{n}")
time.sleep(2)
return n * n
with ThreadPoolExecutor(max_workers=3) as executor:
# 提交任务
futures = [executor.submit(task, i) for i in range(10)]
# 获取结果
for future in futures:
print(f"结果: {future.result()}")
5. 线程高级话题
5.1 GIL(全局解释器锁)的影响
GIL确保同一时间只有一个线程执行Python字节码
对I/O密集型任务影响较小
对CPU密集型任务考虑使用多进程(multiprocessing模块)
5.2 线程局部数据
import threading
local_data = threading.local()
def show_data():
print(f"{threading.current_thread().name}: {getattr(local_data, 'value', None)}")
def worker(value):
local_data.value = value
show_data()
t1 = threading.Thread(target=worker, args=("线程1的数据",), name="Thread-1")
t2 = threading.Thread(target=worker, args=("线程2的数据",), name="Thread-2")
t1.start()
t2.start()
t1.join()
t2.join()
5.3 定时器线程
from threading import Timer
def hello():
print("Hello, 定时器!")
t = Timer(5.0, hello) # 5秒后执行
t.start()
6. 线程最佳实践
避免过度使用线程:线程不是越多越好,要考虑上下文切换开销
优先使用线程池:避免频繁创建销毁线程
合理使用锁:锁粒度要适中,避免死锁
注意线程安全:特别是对共享资源的访问
考虑替代方案:对于CPU密集型任务,考虑多进程或异步IO
加粗样式7. 常见问题与解决方案
7.1 如何停止线程?
Python没有直接停止线程的方法,推荐使用标志位:
import threading
import time
class StoppableThread(threading.Thread):
def __init__(self):
super().__init__()
self._stop_event = threading.Event()
def stop(self):
self._stop_event.set()
def stopped(self):
return self._stop_event.is_set()
def run(self):
while not self.stopped():
print("线程运行中...")
time.sleep(1)
print("线程已停止")
t = StoppableThread()
t.start()
time.sleep(3)
t.stop()
t.join()
7.2 如何处理线程异常?
import threading
import sys
def worker():
try:
raise ValueError("线程内部错误")
except Exception as e:
print(f"捕获线程异常: {e}")
# 可以在这里记录日志或通知主线程
def excepthook(args):
print(f"线程异常: {args.exc_value}")
# 设置线程异常钩子
threading.excepthook = excepthook
t = threading.Thread(target=worker)
t.start()
t.join()
8. 性能对比示例
I/O密集型任务中线程的优势:
import threading
import time
import requests
def download(url):
response = requests.get(url)
print(f"{url} 下载完成,长度: {len(response.content)}")
# 顺序执行
start = time.time()
download("https://www.python.org")
download("https://www.baidu.com")
download("https://www.qq.com")
print(f"顺序执行耗时: {time.time() - start:.2f}秒")
# 多线程执行
start = time.time()
threads = []
for url in ["https://www.python.org", "https://www.baidu.com", "https://www.qq.com"]:
t = threading.Thread(target=download, args=(url,))
threads.append(t)
t.start()
for t in threads:
t.join()
print(f"多线程执行耗时: {time.time() - start:.2f}秒")
9. 总结
Python的threading模块为多线程编程提供了强大的支持。虽然受GIL限制,但在I/O密集型任务、GUI应用和网络请求等场景中,合理使用线程仍能显著提升程序性能。掌握线程同步、通信和线程池等高级特性,可以帮助开发者编写出更高效、更健壮的多线程程序。
最后:
希望你编程学习上不急不躁,按照计划有条不紊推进,把任何一件事做到极致,都是不容易的,加油,努力!相信自己!
文末福利
最后这里免费分享给大家一份Python全套学习资料,希望能帮到那些不满现状,想提升自己却又没有方向的朋友,也可以和我一起来学习交流呀。
包含编程资料、学习路线图、源代码、软件安装包等!【点击这里领取!】
① Python所有方向的学习路线图,清楚各个方向要学什么东西
② 100多节Python课程视频,涵盖必备基础、爬虫和数据分析
③ 100多个Python实战案例,学习不再是只会理论
④ 华为出品独家Python漫画教程,手机也能学习