python多线程-threading|线程同步|线程池|守护线程
作者:YXN-python 阅读量:78 发布日期:2023-08-27
1、线程的基本应用
import threading
def cook():
print("唱歌中...")
def wash():
print("玩手机中...")
# 创建线程对象
# 变量1 = threading.Thread(target=目标函数名称,args=(目标函数的参数元组),name='线程名1' )
thread1 = threading.Thread(target=cook)
thread2 = threading.Thread(target=wash)
# 启动线程
thread1.start()
thread2.start()
# 等待所有线程完成,需要等谁就 写 shei.join()
thread1.join()
thread2.join()
print("完成!")
2、线程同步
借助锁 Lock,每次访问共享资源前,先acquire()上锁,操作完后release()解锁,这样就避免了数据混乱。
import threading
# 全局变量
g_sum = 0
lock = threading.Lock()
def sum_():
global g_sum
for i in range(1000000):
lock.acquire() # 上锁,防止同时访问
g_sum += 1
lock.release() # 解锁,释放控制权
print('sum:{}'.format(g_sum))
if __name__ == '__main__':
sum1_thread = threading.Thread(target=sum_)
sum2_thread = threading.Thread(target=sum_)
sum1_thread.start()
sum2_thread.start()
注意:锁用不好也会出问题,容易形成了死锁。要小心设计,避免循环等待。
3、线程池
线程池(ThreadPoolExecutor)就是预先创建好一些线程,重复利用。
如下:ThreadPoolExecutor创建了一个最多有5个线程的池,map()函数并行执行任务列表中的每个任务。
from concurrent.futures import ThreadPoolExecutor
def task(n):
print(f"执行任务{n}")
with ThreadPoolExecutor(max_workers=5) as executor:
executor.map(task, range(1, 6))
4、守护线程
守护线程:随着主线程的终止而终止,不管当前主线程下有多少子线程没有执行完毕,都会终止。
t.daemon = True 当前的子线程设置为守护线程
import time
import threading
def fun():
print("子线程")
time.sleep(2)
print("子线程结束")
def main():
print("主程序")
t1 = threading.Thread(target=fun,args=(),daemon=False)
t1.daemon = True
t1.start()
time.sleep(1)
print("主程序结束")
if __name__ == '__main__':
main()
代码所示:如果不设置t1.daemon = True 线程守护,主程序会等待线程执行完成后再关闭,输出:主程序-子线程-主程序结束-子线程结束,当设置守护线程后输出:主程序-子线程-主程序结束
5、线程优先级
Python标准库没有直接提供线程优先级的功能,但可以通过队列等间接实现。
如下:使用队列模拟多线程下载图片
import requests
import threading
from queue import Queue
def download_image(url):
response = requests.get(url)
with open(f"image_{url[-4:]}", 'wb') as f:
f.write(response.content)
print(f"下载完成:{url}")
image_urls = ["http://example.com/image1.jpg", "http://example.com/image2.jpg"] # 假设的URL
queue = Queue()
threads = []
for url in image_urls:
queue.put(url)
def worker():
while not queue.empty():
url = queue.get()
download_image(url)
queue.task_done()
for _ in range(3): # 启动3个下载线程
t = threading.Thread(target=worker)
t.start()
threads.append(t)
# 等待所有下载任务完成
for t in threads:
t.join()
print("所有图片下载完成!")
YXN-python
2023-08-27