python中的线程和进程

async:异步的
parallelism:并行
race condition:资源竞争
out of memory:爆内存
GIL:global interpreter lock 全局解释器锁
并发:concurrency,在某个特定的时刻,只允许一条指令执行,只不过线程/任务之间会相互切换,使得宏观上几乎是支持多进程的并发执行。
并行:是指同一时刻有多条指令在多个处理器上同时执行;

一、线程、进程、协程的区别?

  • 进程:是资源分配的单位,进程的切换需要的资源大,效率低。
  • 线程:是操作系统调度的单位。
  • 协程:又称为微线程,协程的切换只是单纯的操作cpu的上下文,资源小,效率高。
    一个程序至少有一个进程,一个进程至少有一个线程。
    在实现多任务时, 线程切换从系统层面远不止保存和恢复 CPU上下文这么简单。 操作系统为了程序运行的高效性每个线程都有自己缓存Cache等等数据,操作系统还会帮你做这些数据的恢复操作。 所以线程的切换非常耗性能。但是协程的切换只是单纯的操作CPU的上下文,所以一秒钟切换个上百万次系统都抗的住。

二、多线程与多进程的应用场景?

  • cpu密集型的任务需要多进程。cpu密集型的任务,指会消耗大量cpu资源的任务,如:求1到10000000000的乘积,或者把一段很长的字编码后又解码。
  • I/O密集型需要使用多线程,如果想要加速,优先使用多线程和ascyio,对于i/o密集型的任务大多数时间都花在i/o的等待上。因此一个线程/任务在等待i/o时,我们只需要切换线程/任务去执行其他的i/o操作就可以。

三、python并发的concurrent模块

在python 中,concurrent是用来完成并发的模块之一。concurrent库是python的内置模块之一,基于threading和multiprocessing两个模块实现的,并对二者进行了很好的封装和集成,使其拥有更加简洁易用的接口函数,无需在考虑start()、join()、lock()等问题。打开concurrent模块(默认安装位于…\Python\Python37\Lib),发现当前其仅内置了一个futures子模块,而futures子模块中,则有3个重要的.py文件,其中_base.py是最主要的模块,提供了大部分并发功能,但属于私有模块,不能被其他程序直接import,另外两个则是process和thread模块,即多进程和多线程,二者均调用_base实现主要并发接口函数。
请添加图片描述

四、多线程的实现,并获取返回值

  • 方法一:多线程的运算结果是没有返回值的,所以需要把多线程的运算结果放入到队列中,然后到主线程中拿出来并进行计算。
import threading
from queue import Queue

def job(l,q):
    sum=0
    for i in l:
        sum=sum+i
    q.put(sum)
    print('xxxxx')

def multithread():
    q=Queue()
    threads=[]
    data=[[1,2,3],[2,3,4],[4,5,6],[5,6,7]]
    for i in range(4):
        t=threading.Thread(target=job,args=(data[i],q))
        threads.append(t)
    for trd in threads:
        trd.start()
    for trd in threads:
        trd.join()  #加载到主线程,等所有线程运行完后返回运行值
    result=[]
    while not q.empty():
        #每次按照顺序拿出一个值
        result.append(q.get())
    print(result)
if __name__=='__main__':
    multithread()

  • 在python3.2开始,标准库为我们提供了concurrent.futures模块,它提供了TheadPoolEexcutor 和ProcessPoolExecutor两个类,实现了对threading和multiprocessing的进一步封装,主线程可以获取某一个线程的状态,以及返回值。当一个线程完成时,主线程能够独立知道。
from concurrent.futures import  ThreadPoolExecutor
from concurrent.futures._base import as_completed

def thread_function(age):
    return age+1
def run_thread_pool(target,args,max_work_count=3):
    with ThreadPoolExecutor(max_workers=max_work_count) as t:
        res=[t.submit(target,i) for i in args]
    return res


if __name__=='__main__':
    args=[1,3,4]
    res=run_thread_pool(thread_function,args)
    print(res)
    for future in as_completed(res):
        data=future.result()
        print(data)
  • 使用threadpoolExecutor的map获取返回值
from concurrent.futures import  ThreadPoolExecutor
def thread_function(age):
    return age+1
def run_thread_pool(target,args,max_work_count=3):
    with ThreadPoolExecutor(max_workers=max_work_count) as t:
        res=[t.submit(target,i) for i in args]
    return res

def thread_function(age):
    for i in age:
        yield i+1

def run_thread_pool(target,args,max_work_count=6):
    with ThreadPoolExecutor(max_workers=max_work_count) as t:
        res=t.map(target,args)
    return res

if __name__=='__main__':
    args=[3,2,11]
    res=run_thread_pool(thread_function,args=(args,))
    for rs in res:
        for j in rs:
            print(j)

参考文章:https://blog.csdn.net/d1240673769/article/details/123888922

多线程和多进程使用实例

import requests
import time
import threading
import multiprocessing


def attack_work(name, num):
    count = 1
    while True:
        if count > num:
            break
        url = "http://www.baidu.com/"
        headers = {
            "Referer": "http://www.baidu.com"
        }
        response = requests.get(url, headers=headers)
        print("{},第 {} 次请求----\n".format(name, count))
        count += 1


def timeLogger(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)
        duration = time.time() - start_time
        print("function: {} took {}s.".format(func.__name__, round(duration, 3)))

    return wrapper


@timeLogger
def multi_thread(m, n):  # m为开启线程数,n为每个线程攻击的次数
    print("######启动{}个线程进行请求,每个线程请求{}次,共进行{}次请求######\n".format(m, n, m * n))
    lst = []
    for i in range(m):
        tname = '线程:threadid-{}'.format(i + 1)
        t = threading.Thread(target=attack_work, name=tname, args=(tname, n))
        t.start()
        lst.append(t)

    for t in lst:
        t.join()
    print("执行完成-----")



@timeLogger
def multi_process(m, n):  # m为开启进程数,n为每个进程攻击的次数
    print("######启动{}个进程进行请求,每个进程请求{}次,共进行{}次请求######\n".format(m, n, m * n))
    lst = []
    for i in range(m):
        pname = "进程:processid-{}".format(i + 1)
        p = multiprocessing.Process(target=attack_work, name=pname, args=(pname, n))
        p.start()
        lst.append(p)

    for p in lst:
        p.join()
    print("执行完成-----")


if __name__ == "__main__":
    #multi_thread(20, 100)
    multi_process(20,100)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值