threading
threading
模块用于创建和管理线程。import threading
def print_numbers():
for i in range(5):
print(f"Number: {i}")
# 创建线程
thread = threading.Thread(target=print_numbers)
# 启动线程
thread.start()
# 等待线程执行完毕
thread.join()
print("主线程结束")
解释:
target
指向需要在线程中执行的函数。start()
启动线程。join()
等待线程执行完毕后再继续主线程的操作。多个线程访问同一资源时可能会发生冲突。
import threading
import time
counter = 0
def increase():
global counter
for _ in range(100000):
current = counter; # 使用这个数据, 假设是某数据库获取
time.sleep(0.0000001) # 模拟有逻辑执行. 其他线程介入
counter = current + 1 # 对原数据做操作
# 创建两个线程同时增加 counter
t1 = threading.Thread(target=increase)
t2 = threading.Thread(target=increase)
t1.start()
t2.start()
t1.join()
t2.join()
print(f"最终结果: {counter}")
输出:
理论上结果应为 200000,但由于线程间竞争,结果可能出错。
Lock
)import threading
import time
lock = threading.Lock()
counter = 0
def increase_with_lock():
global counter
for _ in range(100000):
with lock: # 锁住代码块
current = counter; # 使用这个数据, 假设是某数据库获取
time.sleep(0.0000001) # 模拟有逻辑执行. 其他线程介入
counter = current + 1 # 对原数据做操作
t1 = threading.Thread(target=increase_with_lock)
t2 = threading.Thread(target=increase_with_lock)
t1.start()
t2.start()
t1.join()
t2.join()
print(f"最终结果: {counter}")
import threading
import time
def background_task():
while True:
print("后台任务运行中...")
time.sleep(2)
t = threading.Thread(target=background_task, daemon=True)
t.start()
time.sleep(5)
print("主线程结束")
解释:
即使后台任务没有完成,当主线程结束时,它也会终止。
multiprocessing
模块)。Condition
等同步机制协调线程工作。import threading
import requests
urls = [
"https://www.baidu.com",
"https://www.sina.com.cn",
"https://www.qq.com",
]
def download_content(url):
response = requests.get(url)
print(f"{url} 的内容长度为: {len(response.text)}")
threads = []
for url in urls:
t = threading.Thread(target=download_content, args=(url,))
threads.append(t)
t.start()
for t in threads:
t.join()
print("所有网页下载完成")
解释:
concurrent.futures
)Python 提供了 concurrent.futures.ThreadPoolExecutor
,用于方便地创建和管理线程池。
from concurrent.futures import ThreadPoolExecutor
import time
def task(n):
print(f"任务 {n} 开始")
time.sleep(2) # 模拟耗时任务
print(f"任务 {n} 完成")
return n * 2
# 创建线程池,并提交多个任务
with ThreadPoolExecutor(max_workers=3) as executor:
futures = [executor.submit(task, i) for i in range(5)]
# 获取每个任务的结果
for future in futures:
print(f"结果: {future.result()}")
解释:
max_workers=3
:线程池中最多同时运行 3 个线程。executor.submit(task, i)
:向线程池提交任务并执行。future.result()
:等待任务完成,并获取结果。输出示例:
任务 0 开始
任务 1 开始
任务 2 开始
任务 0 完成
任务 3 开始
任务 1 完成
任务 4 开始
任务 2 完成
任务 3 完成
任务 4 完成
结果: 0
结果: 2
结果: 4
结果: 6
结果: 8
from concurrent.futures import ThreadPoolExecutor
import requests
urls = [
"https://www.baidu.com",
"https://www.sina.com.cn",
"https://www.qq.com",
]
def fetch_content(url):
response = requests.get(url)
return f"{url} 的内容长度为: {len(response.text)}"
# 创建线程池并行下载
with ThreadPoolExecutor(max_workers=5) as executor:
results = executor.map(fetch_content, urls)
# 打印结果
for result in results:
print(result)
解释:
executor.map()
:将任务分配给线程池中的线程并行执行。future.result()
时捕获任务执行过程中的异常,确保程序稳定。with ThreadPoolExecutor(max_workers=3) as executor:
futures = [executor.submit(task, i) for i in range(5)]
for future in futures:
try:
print(f"结果: {future.result()}")
except Exception as e:
print(f"任务执行出错: {e}")
多线程在 CPU 密集型任务中的性能受限
I/O 密集型任务的优势
import threading
import time
def cpu_task():
total = 0
for i in range(10**7):
total += i
# 使用多线程执行 CPU 密集型任务
start = time.time()
# 创建 2 个线程做 “+” 操作
threads = [threading.Thread(target=cpu_task) for _ in range(2)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
print(f"多线程耗时: {time.time() - start:.2f} 秒")
输出:
即使有多个线程,CPU 密集型任务也不会快太多,因为 GIL 限制了并行性。
import threading
import time
def io_task():
time.sleep(2) # 模拟 I/O 操作
# 使用多线程执行 I/O 密集型任务
start = time.time()
# 快速创建5个线程, 模拟执行IO传输的调用
threads = [threading.Thread(target=io_task) for _ in range(5)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()
print(f"多线程耗时: {time.time() - start:.2f} 秒")
输出:
由于 GIL 会在 time.sleep()
等 I/O 操作时释放,因此多个线程可以并发运行,程序的总耗时会缩短。
多进程替代多线程:
使用 multiprocessing
模块创建多个进程,每个进程有独立的 GIL,可以充分利用多核 CPU。
from multiprocessing import Process
import time
def cpu_task():
total = 0
for i in range(10**7):
total += i
# 多进程创建的代码 需要 if __name__ == '__main__':块来保护代码
if __name__ == "__main__":
# 创建多个进程
processes = [Process(target=cpu_task) for _ in range(2)]
start = time.time()
for p in processes:
p.start()
for p in processes:
p.join()
print(f"多线程耗时: {time.time() - start:.2f}") # 性能上优于上面的同样的线程CPU密集型代码效率
每日学学又记记、明天单车变摩托 !