windows:
当创建进程时,会将当前py文件由上到下重新执行一次,所以我们要将执行代码放在__ main __ 中。
linux:
在linux系统中,会直接复制一分代码去执行
这里有解决问题的办法:
国内:开源中国,CSDN, cnblods,https://www.v2ex.com/
国外:Stack Overflow
GIL: 全局解释器锁
Cpython的内存管理不是线程安全,在同一进程开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势
GIL全局解释锁,本质上就是一把互斥锁,保证数据的安全
GIL全局解释器的优缺点:
1.优点:
保证数据的安全
2.缺点:
单个进程下,开启多个线程,牺牲执行效率,无法实现并行,只能实现并发
,只能实现并发。
IO密集型,多线程
计算密集型,多进程
io密集型任务,每个任务4s
单核:
开启的线程比进程节省资源
多核:
多线程:
开启4个子线程:16s
多进程:
开启4个进程:16s + 申请开启资源消耗的时间
计算密集型任务,每个任务4s
单核:
开启线程比进程节省资源
多核:
多线程:
开启4个子线程:16s
多进程:
开启多个进程:4s
什么是协程?
进程:资源单位
线程:执行单位
协程: 单线程下实现并发
在io密集的情况下,使用协程能提高最高效率
ps:协程不是任何单位,只是一个个程序员臆想出来的东西
协成的目的是为了:
手动实现‘遇到io切换+保存状态’去欺骗操作系统,让操作系统误以为没有io操作,将cpu的执行权限给你
from gevent import monkey # 猴子补丁
monkey.patch_all() # 监听所有的任务是否有io操作
from gevent import spawn # 任务
from gevent import joinall
import time
def task1():
print('start from task1...')
time.sleep(1)
print('end from task1...')
def task2():
print('start from task2...')
time.sleep(2)
print('end from task2...')
def task3():
print('start from task3...')
time.sleep(3)
print('end from task3...')
if __name__ == '__main__':
start_time = time.time()
sp1 = spawn(task1)
sp2 = spawn(task2)
sp3 = spawn(task3)
# sp1.start()
# sp2.start()
# sp3.start()
# sp1.join()
# sp2.join()
# sp3.join()
joinall([sp1, sp2, sp3])
end_time = time.time()
print(f'消耗时间:{end_time - start_time}')
start from task1...
start from task2...
start from task3...
end from task1...
end from task2...
end from task3...
消耗时间:3.0070078372955322
线程池与进程池中的回调函数的使用:
# from gevent import monkey;monkey.patch_all()
# from gevent import spawn
# import time
#
#
# def task1(name):
# print(name)
# print('start')
# time.sleep(1)
# print('end')
#
#
# def task2():
# print('start')
# time.sleep(3)
# print('end')
#
#
# def task3():
# print('start')
# time.sleep(5)
# print('end')
#
# if __name__ == '__main__':
# spawn(task1, 'tank')
# spawn(task2)
# g = spawn(task3)
# g.join()
# 线程池与进程池
# 进程池
# from concurrent.futures import ProcessPoolExecutor
# import time
# # 池子对象: 内部可以帮你提交50个启动进程的任务
# p_pool = ProcessPoolExecutor(50)
#
#
# def task1(n):
# print(f'from task1...{n}')
# time.sleep(10)
#
#
# if __name__ == '__main__':
# n = 1
# while True:
# # 参数1: 函数名
# # 参数2: 函数的参数1
# # 参数3: 函数的参数2
# # submit(参数1, 参数2, 参数3)
# p_pool.submit(task1, n)
# n += 1
# 线程池
# from concurrent.futures import ThreadPoolExecutor
# import time
# # 池子对象: 内部可以帮你提交50个启动进程的任务
# p_pool = ThreadPoolExecutor(50)
#
#
# def task1(n):
# print(f'from task1...{n}')
# time.sleep(10)
#
#
# if __name__ == '__main__':
# n = 1
# while True:
# # 参数1: 函数名
# # 参数2: 函数的参数1
# # 参数3: 函数的参数2
# # submit(参数1, 参数2, 参数3)
# p_pool.submit(task1, n)
# n += 1
# add_done_callback
# from concurrent.futures import ThreadPoolExecutor
# import time
# # 池子对象: 内部可以帮你提交50个启动进程的任务
# p_pool = ThreadPoolExecutor(50)
#
#
# def task1(n):
# print(f'from task1...{n}')
# time.sleep(5)
# return 'tank'
#
#
# def get_result(obj):
# # print(obj.__dict__)
# # print(obj._result)
# result = obj.result()
# print(result)
#
#
# if __name__ == '__main__':
# n = 1
# while True:
# # 参数1: 函数名
# # 参数2: 函数的参数1
# # 参数3: 函数的参数2
# # submit(参数1, 参数2, 参数3)
# # add_done_callback(参数1),会将submit提交的task1执行的结果,传给get_result中的第一个参数,第一个参数是一个对象。
# p_pool.submit(task1, n).add_done_callback(get_result)
# n += 1