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篇 多线程和多进程的更多相关文章

  1. python分别使用多线程和多进程获取所有股票实时数据

    python分别使用多线程和多进程获取所有股票实时数据   前一天简单介绍了python怎样获取历史数据和实时分笔数据,那么如果要获取所有上市公司的实时分笔数据,应该怎么做呢? 肯定有人想的是,用一个 ...

  2. python爬虫之多线程、多进程+代码示例

    python爬虫之多线程.多进程 使用多进程.多线程编写爬虫的代码能有效的提高爬虫爬取目标网站的效率. 一.什么是进程和线程 引用廖雪峰的官方网站关于进程和线程的讲解: 进程:对于操作系统来说,一个任 ...

  3. 第十章:Python高级编程-多线程、多进程和线程池编程

    第十章:Python高级编程-多线程.多进程和线程池编程 Python3高级核心技术97讲 笔记 目录 第十章:Python高级编程-多线程.多进程和线程池编程 10.1 Python中的GIL 10 ...

  4. python中的多线程和多进程

    一.简单理解一下线程和进程 一个进程中可有多个线程,线程之间可共享内存,进程间却是相互独立的.打比方就是,进程是火车,线程是火车厢,车厢内人员可以流动(数据共享) 二.python中的多线程和多进程 ...

  5. 【Python之路】特别篇--多线程与多进程

    并发 与 并行 的区别: 解释一:并发是在同一实体上的多个事件,并行是在不同实体上的多个事件: 解释二:并发是指两个或多个事件在同一时间间隔发生,而并行是指两个或者多个事件在同一时刻发生. 并发:就是 ...

  6. Python之threading多线程,多进程

    1.threading模块是Python里面常用的线程模块,多线程处理任务对于提升效率非常重要,先说一下线程和进程的各种区别,如图 概括起来就是 IO密集型(不用CPU) 多线程计算密集型(用CPU) ...

  7. python基础之多线程与多进程(二)

    上课笔记整理: 守护线程的作用,起到监听的作用 一个函数连接数据库 一个做守护线程,监听日志 两个线程同时取一个数据 线程---->线程安全---->线程同时进行操作数据. IO操作--- ...

  8. Python系列之多线程、多进程

    线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程. Python的标准库提供 ...

  9. python之路-----多线程与多进程

    一.进程和线程的概念 1.进程(最小的资源单位): 进程:就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成. 程序:我们编写的程序用来描述进程要完成哪些功能以 ...

随机推荐

  1. IDEA 最实用快捷键【MAC版本】

    目录 option + F7 Ctrl + B / Ctrl +鼠标左键(一键两用,可以无限循环的跳过来跳过去,我跳过去了,我又跳回去了) command + E (这个快捷键很有用,为什么我老是用不 ...

  2. typora的一些使用

    1.介绍typora 支持markdown语法的一款写作app 真的足够简洁高效 2. typora和其他工具配合实现功能 如插入图片 截图 gif等等图库 smms图库的使用 需要使用PicGo和s ...

  3. C#解决WebClient不能下载https网页内容

    在下载之前,执行以下代码即可: if (stUrl.Substring(0, 5) == "https") { // 解决WebClient不能通过https下载内容问题 Serv ...

  4. java IO教程《四》

    properties使用 什么是Properties? Properties(Java.util.Properties),该类主要用于读取Java的配置文件,不同的编程语言有自己所支持的配置文件,配置 ...

  5. GStreamer 1.18.4稳定的错误修复版本

    GStreamer 1.18.4稳定的错误修复版本GStreamer团队宣布最喜欢的跨平台多媒体框架的稳定的1.18版本系列中的另一个错误修复版本!此版本仅包含错误修复和重要的安全修复程序,并且从1. ...

  6. CVPR2020论文解析:视觉算法加速

    CVPR2020论文解析:视觉算法加速 GPU-Accelerated Mobile Multi-view Style Transfer 论文链接:https://arxiv.org/pdf/2003 ...

  7. AIFramework框架Jittor特性(上)

    AIFramework框架Jittor特性(上)

  8. 稀疏性如何为AI推理增加难度

    稀疏性如何为AI推理增加难度 NVIDIA Ampere架构使数学运算加倍,以加速对各种神经网络的处理. 如果曾经玩过游戏Jenga,那么将有一些AI稀疏感. 玩家将木制积木交叉成一列.然后,每个玩家 ...

  9. NVIDIA GPUs上深度学习推荐模型的优化

    NVIDIA GPUs上深度学习推荐模型的优化 Optimizing the Deep Learning Recommendation Model on NVIDIA GPUs 推荐系统帮助人在成倍增 ...

  10. 微调BERT:序列级和令牌级应用程序

    微调BERT:序列级和令牌级应用程序 Fine-Tuning BERT for Sequence-Level and Token-Level Applications 为自然语言处理应用程序设计了不同 ...