定义
1, 进程: 就是一组资源的集合. 一个程序就是一个进程.
线程是用来干活的, 只有进程的话是没办法运行的, 进程里其实是线程在具体干活的.
线程和线程之间是互相独立的.
- import threading #引入线程模块
- import time
- def run():
- time.sleep(5)
- print('over')
- start_time=time.time()
- run()
- run()
- run()
- run()
- end_time=time.time()
- print('run_time', end_time-start_time)
- # 结果: run_time=20.38954234234
上面这个例子是单线程执行的, 运行时间是 20 多秒, 如果使用多线程, 则会并行执行, 执行结果应该是 5 秒左右.
- import threading
- import time
- def run():
- time.sleep(5)
- print('over')
- start_time=time.time()
- thread_list = []
- for i in range(5):
- t=threading.Thread(target=run) #实例化一个线程
- t.start() #启动这个线程
- thread_list.append(t)
- for thread in thread_list:
- thread.join() #主线程等待子线程
- end_time=time.time()
- print('run_time=', end_time-start_time)
单线程下载网页:
- import requests,time,threading
- from hashlib import md5
- result_list = {}
- def down_load_pic(url):
- req = requests.get(url)
- m = md5(url.encode()) #把 url 转换为二进制 md5 下
- file_name = m.hexdigest()+'.png' #拼接文件名
- with open(file_name ,'wb') as fw:
- fw.write(req.content)
- # return file_name
- result_list[file_name] = threading.current_thread()
- url_list = ['http://www.nnzhp.cn/wp-content/uploads/2019/10/f410afea8b23fa401505a1449a41a133.png',
- 'http://www.nnzhp.cn/wp-content/uploads/2019/11/481b5135e75c764b32b224c5650a8df5.png',
- 'http://www.nnzhp.cn/wp-content/uploads/2019/11/b23755cdea210cfec903333c5cce6895.png',
- 'http://www.nnzhp.cn/wp-content/uploads/2019/11/542824dde1dbd29ec61ad5ea867ef245.png']
- start_time = time.time()
- for url in url_list:
- down_load_pic(url)
- end_time = time.time()
- print(end_time - start_time)
- # 结果: 4.439253807067871
多线程下载网页:
- import requests,time,threading
- from hashlib import md5
- result_list = {}
- def down_load_pic(url):
- req = requests.get(url)
- m = md5(url.encode()) #把 url 转换为二进制 md5 下
- file_name = m.hexdigest()+'.png' #拼接文件名
- with open(file_name ,'wb') as fw:
- fw.write(req.content)
- # return file_name
- result_list[file_name] = threading.current_thread()
- url_list = ['http://www.nnzhp.cn/wp-content/uploads/2019/10/f410afea8b23fa401505a1449a41a133.png',
- 'http://www.nnzhp.cn/wp-content/uploads/2019/11/481b5135e75c764b32b224c5650a8df5.png',
- 'http://www.nnzhp.cn/wp-content/uploads/2019/11/b23755cdea210cfec903333c5cce6895.png',
- 'http://www.nnzhp.cn/wp-content/uploads/2019/11/542824dde1dbd29ec61ad5ea867ef245.png']
- start_time = time.time()
- for url in url_list:
- t = threading.Thread(target=down_load_pic,args=(url,)) #args 是存参数的, 如果里面只有一个参数的话, 一定要在这个参数后面加一个逗号, 因为是保存在元组里, 如果不加逗号, 它会默认为是字符串 应该写成: args=(url,)
- t.start() while threading.activeCount()!=1: pass end_time = time.time() print(end_time - start_time)
- # 结果: 3.959226369857788
一个进程里面至少有一个线程, 这个线程就是主线程.
主线程只是调度用的, 它把子线程招来之后就完事了, 因此如果要统计运行时间, 必须要让主线程等待所有的子线程都执行完后再记录结束时间.
2, 守护线程, 什么是守护线程呢, 就相当于你是一个国王 (非守护线程), 然后你有很多仆人 (守护线程), 这些仆人都是为你服务的, 一但你死了, 那么你的仆人都给你陪葬.
- # 主线程结束, 守护线程立马死掉.
- import threading,time
- def down_load():
- time.sleep(5)
- print("运行完了")
- for i in range(10):
- t = threading.Thread(target=down_load)
- t.setDaemon(True) #设置子线程为守护线程
- t.start()
- print('over')
3, 线程锁, 线程锁就是, 很多线程一起在操作一个数据的时候, 可能会有问题, 就要把这个数据加个锁, 同一时间只能有一个线程操作这个数据.
- import threading
- from threading import Lock
- num = 0
- lock = Lock()# 申请一把锁
- def run():
- global num
- lock.acquire()# 加锁
- num+=1
- lock.release()# 解锁
- lis = []
- for i in range(5):
- t = threading.Thread(target=run)
- t.start()
- lis.append(t)
- for t in lis:
- t.join()
- print('over',num)
4, 线程锁, 线程锁就是, 很多线程一起在操作一个数据的时候, 可能会有问题, 就要把这个数据加个锁, 同一时间只能有一个线程操作这个数据.
- # 多个线程操作同一个数据的时候, 就得加锁
- import threading
- num = 0
- lock = threading.Lock() #申请一把锁
- def add():
- global num
- # lock.acquire()# 加锁
- # num+=1
- # lock.release()# 解锁 #不解锁, 就会产生死锁, 会一直在等待
- with lock:# 简写, 用 with 也会帮你加锁, 解锁
- num+=1
- for i in range(20):
- t = threading.Thread(target=add,)
- t.start()
- while threading.activeCount() !=1:
- pass
来源: http://www.bubuko.com/infodetail-3296928.html