您现在的位置是:网站首页 > 博客日记 >

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