协程

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

原文地址:https://www.cnblogs.com/godlover/p/12018992.html