python 16篇 多线程和多进程
1、概念
线程、进程
进程
一个程序,它是一组资源的集合
一个进程里面默认是有一个线程的,主线程
多进程是可以利用多核cpu的
线程
最小的执行单位
线程和线程之间是互相独立的
主线程等待子线程执行结束
线程和线程之间,数据是共享的。
守护线程:
只要主线程执行完成,不管子线程有没有执行完成,全部都结束
一个电脑有几核CPU就只能同时运行几个任务,比如4核CPU只能同时运行4个线程
我们在操作电脑时,感觉是同时运行多个任务,是因为CPU的运算速度很快,有上下文切换,我们感觉不到
python里的多线程利用不了多核CPU,比如我的电脑是8核的CPU,起100个线程,这100个线程都是在一个CPU里面执行,其他7个CPU是空闲的
因为线程之间数据是共享的,同时来处理数据会乱,GLI全局解释器锁,保证线程都在同一个CPU上运行
多进程可以利用多核CPU
CPU密集型任务,用多进程-->消耗CPU比较多
IO(磁盘IO,网络IO)密集型任务,用多线程-->消耗IO比较多
#1、多线程,线程之间数据是共享的
#2、多进程,进程之间数据是独立的
2、多线程
2.1、多线程代码
串行的方式是执行完一个,再接着执行第二个
多线程是同时启用多个线程去操作
import random
import threading
import time
def clean():
print('打扫卫生')
time.sleep(2)
def xiyifu():
print('洗衣服')
time.sleep(1)
def cook():
print('做饭')
time.sleep(3) def export_data(db,excel):
print(threading.current_thread())
print('export_data %s %s' % (db, excel))
time.sleep(random.randint(1, 5))
# 单线程
start_time = time.time()
clean()
xiyifu()
cook()
end_time = time.time()
print('单线程或串行的运行时间', end_time - start_time)
# 多线程
start_time = time.time()
t = threading.Thread(target=clean) # 这里只写函数名称
t2 = threading.Thread(target=xiyifu)
t3 = threading.Thread(target=cook)
t.start()
t2.start()
t3.start()
# 以下这种是并行执行,如果每个子线程启动后就调用join方法,就变成了串行,不可取
t.join() # 主线程等待子线程
t2.join()
t3.join()
end_time = time.time()
print('多线程并行的运行时间', end_time - start_time)
time.sleep(4) # 过了4s后,后面开启的线程执行完毕就没有了
print(threading.active_count()) # 当前的线程数
执行结果

2.2、多线程的时间统计
import random
import threading
import time
def clean():
print('打扫卫生')
time.sleep(2)
def xiyifu():
print('洗衣服')
time.sleep(1)
def cook():
print('做饭')
time.sleep(3) def export_data(db,excel):
print(threading.current_thread())
print('export_data %s %s' % (db, excel))
time.sleep(random.randint(1, 5))
# 多线程
start_time = time.time()
t = threading.Thread(target=clean) # 这里只写函数名称
t2 = threading.Thread(target=xiyifu)
t3 = threading.Thread(target=cook)
t.start()
t2.start()
t3.start()
end_time = time.time()
print('多线程并行的运行时间', end_time - start_time)
执行结果

正常执行应该是6秒多一点,这里是因为只是主线程执行的时间,没有计算子线程执行的时间,如何解决该问题?
两种方法:
# 方法一:等待子线程执行结束,把启动的子线程放到list中,在循环调用t.join
thread_list = []
for i in range(10):
t = threading.Thread(target=export_data)
thread_list.append(t)
t.start()
for t in thread_list:
t.join()
print('线程都运行完了') # 方法二:等待子线程执行结束,通过判断当前线程数
for i in range(10):
t = threading.Thread(target=export_data, args=['db1', 'a.xlsx']) # 传参
t.start()
while threading.active_count() != 1:
pass
print('线程都运行完了')
2.3、多线程传参
可以用数组的方式来传参,args=['lxy']
import threading
import requests from day09.ketanglianxi_09 import zidonghuayilai_instal def down_load_pic(url):
r = requests.get(url)
file_name = zidonghuayilai_instal.InstallRequrie.md5(url) + '.jpg'
with open(file_name, 'wb') as fw:
fw.write(r.content) urls = [
'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3353166494,2700282750&fm=26&gp=0.jpg',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603003159808&di=7a97fdd275ec4e0fc4ab54bdb8a2e703&imgtype=0&src=http%3A%2F%2Fwww.pc6.com%2Fup%2F2011-12%2F201112918444441530.jpg',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603003159808&di=0ae20fe3bd8759c059cb4432938e4062&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20181209%2F38467a58f9264ca68eefa37719b4b739.jpeg',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603003159807&di=5040439b916279a7106a7660b7e0168a&imgtype=0&src=http%3A%2F%2Fimg1.cache.netease.com%2Fcatchpic%2FE%2FE5%2FE5DD0A8099E2D28226465C6894F7A7A1.jpg'
] for url in urls:
t = threading.Thread(target=down_load_pic, args=[url])
t.start()
while threading.active_count() != 1:
pass
print('所有图片下载完毕')
2.4、多线程获取函数返回值
多线程运行函数时,是没有办法获取到函数的返回值,所以可以定义一个全局的list,把函数的返回结果存到list就可以了
case_result = []
def run_case(case_name):
print('run case over...')
case_result.append({case_name,'success'})
2.5、守护线程
守护线程,一旦主线程死掉,不管守护线程有没有执行完成,守护线程全部都结束
import random
import threading
import time def talk(name):
print('正在和%s聊天' % name)
time.sleep(random.randint(1, 5))
print('和%s聊完了' % name) t = threading.Thread(target=talk, args=['lhy'])
t.setDaemon(True) # 设置成守护线程
t.start() t = threading.Thread(target=talk, args=['xiaohei'])
t.setDaemon(True)
t.start() t = threading.Thread(target=talk, args=['xiaobai'])
t.setDaemon(True)
t.start()
# 等待所有子线程都执行完
# while threading.active_count() != 1:
# pass
print('聊完了') # 未等子进程执行完,主线程就执行完了,那么守护线程也立马结束
2.6、线程锁
多个线程同时操作同一个数据时,会有问题,这个时候需要用到线程锁
线程锁需要设置锁定时长,数据操作完成后,需要解锁,不然其他线程会进入无线等待
import threading count = 0
lock = threading.Lock()
def add():
global count
for i in range(1000000):
# 锁的第一种写法 如果忘记写解锁或锁未释放,就会造成死锁
lock.acquire() # 加锁
count += 1
lock.release() # 解锁
#第二种写法
# with lock:
# count += 1
for i in range(2):
t = threading.Thread(target=add)
t.start()
while threading.active_count() != 1:
pass
print(count)
2.7 线程池
import threading
import requests
import threadpool
from day09.ketanglianxi_09 import zidonghuayilai_instal def down_load_pic(url):
print(threading.current_thread())
r = requests.get(url)
file_name = zidonghuayilai_instal.InstallRequrie.md5(url) + '.jpg'
with open(file_name, 'wb') as fw:
fw.write(r.content) urls = [
'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=3353166494,2700282750&fm=26&gp=0.jpg',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603003159808&di=7a97fdd275ec4e0fc4ab54bdb8a2e703&imgtype=0&src=http%3A%2F%2Fwww.pc6.com%2Fup%2F2011-12%2F201112918444441530.jpg',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603003159808&di=0ae20fe3bd8759c059cb4432938e4062&imgtype=0&src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20181209%2F38467a58f9264ca68eefa37719b4b739.jpeg',
'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1603003159807&di=5040439b916279a7106a7660b7e0168a&imgtype=0&src=http%3A%2F%2Fimg1.cache.netease.com%2Fcatchpic%2FE%2FE5%2FE5DD0A8099E2D28226465C6894F7A7A1.jpg'
]
pool = threadpool.ThreadPool(3)
reqs = threadpool.makeRequests(down_load_pic, urls) # 让它给子线程分配数据
[pool.putRequest(req) for req in reqs]
# 上面一行代码等同于下面2行代码
for req in reqs:
pool.putRequest(req)
pool.wait() # 等待子线程执行结束
3、多进程
import multiprocessing import time lock = multiprocessing.Lock() # 进程锁
lock.acquire()# 加锁
lock.release()# 解锁
def make_money():
print('开始赚钱')
time.sleep(10)
def star_process():
for i in range(5):
p = multiprocessing.Process(target=make_money)
# 如果传参,p = multiprocessing.Process(target=make_money,args=[])
p.start()
# 等待子进程执行完毕
while len(multiprocessing.active_children()) != 1:
pass
print('运行结束')
# p = multiprocessing.Process(target=make_money)
# p.start()
# star_process() # 必须写在__name__ == '__main__'中
if __name__ == '__main__':
star_process()
4、队列
# 队列 和list差不多
import queue
import random
import threading import time orders_q = queue.Queue() # 生产者/消费者模式
def producer():
for i in range(100):
order_id = random.randint(1, 99999)
print('订单生成,orderid=%d' % order_id)
orders_q.put(order_id)
time.sleep(1) def consumer():
while True:
if orders_q.qsize() > 0:
order_id = orders_q.get()
print('consumer1--订单落库', order_id) def consumer2():
while True:
if orders_q.qsize() > 0:
order_id = orders_q.get()
print('consumer2--订单落库', order_id)
t = threading.Thread(target=producer)
t.start() t = threading.Thread(target=consumer)
t.start() t = threading.Thread(target=consumer2)
python 16篇 多线程和多进程的更多相关文章
- python分别使用多线程和多进程获取所有股票实时数据
python分别使用多线程和多进程获取所有股票实时数据 前一天简单介绍了python怎样获取历史数据和实时分笔数据,那么如果要获取所有上市公司的实时分笔数据,应该怎么做呢? 肯定有人想的是,用一个 ...
- python爬虫之多线程、多进程+代码示例
python爬虫之多线程.多进程 使用多进程.多线程编写爬虫的代码能有效的提高爬虫爬取目标网站的效率. 一.什么是进程和线程 引用廖雪峰的官方网站关于进程和线程的讲解: 进程:对于操作系统来说,一个任 ...
- 第十章:Python高级编程-多线程、多进程和线程池编程
第十章:Python高级编程-多线程.多进程和线程池编程 Python3高级核心技术97讲 笔记 目录 第十章:Python高级编程-多线程.多进程和线程池编程 10.1 Python中的GIL 10 ...
- python中的多线程和多进程
一.简单理解一下线程和进程 一个进程中可有多个线程,线程之间可共享内存,进程间却是相互独立的.打比方就是,进程是火车,线程是火车厢,车厢内人员可以流动(数据共享) 二.python中的多线程和多进程 ...
- 【Python之路】特别篇--多线程与多进程
并发 与 并行 的区别: 解释一:并发是在同一实体上的多个事件,并行是在不同实体上的多个事件: 解释二:并发是指两个或多个事件在同一时间间隔发生,而并行是指两个或者多个事件在同一时刻发生. 并发:就是 ...
- Python之threading多线程,多进程
1.threading模块是Python里面常用的线程模块,多线程处理任务对于提升效率非常重要,先说一下线程和进程的各种区别,如图 概括起来就是 IO密集型(不用CPU) 多线程计算密集型(用CPU) ...
- python基础之多线程与多进程(二)
上课笔记整理: 守护线程的作用,起到监听的作用 一个函数连接数据库 一个做守护线程,监听日志 两个线程同时取一个数据 线程---->线程安全---->线程同时进行操作数据. IO操作--- ...
- Python系列之多线程、多进程
线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程. Python的标准库提供 ...
- python之路-----多线程与多进程
一.进程和线程的概念 1.进程(最小的资源单位): 进程:就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成. 程序:我们编写的程序用来描述进程要完成哪些功能以 ...
随机推荐
- Vue之前后端交互
Vue之前后端交互 一.前后端交互模式 接口调用方式 原生ajax 基于jQuery的ajax fetch axios 异步 JavaScript的执行环境是「单线程」 所谓单线程,是指JS引擎中负责 ...
- sql批量插入缓慢
1.有一个普通的表t_asset,只有2个字段id,ip 没有索引 2.当用insert into t_asset(id,ip) values(?,?),(?,?) 1200多条记录时,发现竟然用了3 ...
- java IO教程《四》
properties使用 什么是Properties? Properties(Java.util.Properties),该类主要用于读取Java的配置文件,不同的编程语言有自己所支持的配置文件,配置 ...
- OpenCV读写图像文件解析
OpenCV读写图像文件解析 imdecode 从内存中的缓冲区读取图像. C++:Mat imdecode(InputArray buf, int flags) C++:Mat imdecode(I ...
- java后端知识点梳理——Spring
开篇:感谢我是祖国的花朵,java3y,三太子敖丙等优秀博主!他们的文章为我学习java提供了莫大的帮助,膜拜大神! Spring的优点有哪些呢? Spring的依赖注入将对象之间的依赖关系交给了框架 ...
- 深入理解java虚拟机笔记Chapter2
java虚拟机运行时数据区 首先获取一个直观的认识: 程序计数器 线程私有.各条线程之间计数器互不影响,独立存储. 当前线程所执行的字节码行号指示器.字节码解释器工作时通过改变这个计数器值选取下一条需 ...
- 从一条sql报错解决过程学习程序员查bug的思路
从oracle迁移数据到达梦后,发现数据库默认值都丢失了.于是我想从oracle数据库将默认值查出来,在达梦数据库加回去. 于是上网查了一下,看怎么获取oracle数据库字段默认值信息,找到了这个sq ...
- Reactor3 中文文档(用户手册)
文章很长,建议收藏起来,慢慢读! 疯狂创客圈为小伙伴奉上以下珍贵的学习资源: 疯狂创客圈 经典图书 : <Netty Zookeeper Redis 高并发实战> 面试必备 + 大厂必备 ...
- Mysql优化(出自官方文档) - 第七篇
Mysql优化(出自官方文档) - 第七篇 目录 Mysql优化(出自官方文档) - 第七篇 Optimizing Data Change Statements 1 Optimizing INSERT ...
- Spring Boot下的一种导出CSV文件的代码框架
1.前言 CSV,逗号分隔值(Comma-Separated Values),即为逗号分隔的文本文件.如果值中含有逗号.换行符.制表符(Tab).单引号及双引号,则需要用双引号括起来:如果值中包含 ...