zoukankan      html  css  js  c++  java
  • 并发编程——进程池线程池、协程、IO模型

    1、socket 服务端实现高并发 网络编程服务端需要满足的要求:

    ①固定的IP和port

    ②24H提供服务

    ③能实现并发

    # socket实现并发
    # seerver
    import socket
    from threading import Thread
    server = socket.socket()
    server.bind(('127.0.0.1',8080))
    server.listen(5)
    
    
    def communicate():
        # 通讯循环
    	while True:
    		try:
    			# 接收数据
    			data = conn.recv(1024)
                if len(data) == 0:break
                print(data)
                conn.send(data.upper())
    		except ConnectionResetError:
                break
        conn.close()
    
    #连接循环
    while TRUE:
        conn addr = server.accept()
    	# 开启线程
    	t = Thread(target = communicate,args=(conn,))
    	t.start()
    server
    # cliet 
    import socket
    
    client = socket.socket()
    client.connect(('127.0.0.1',8080))
    
    # 通讯循环
    while True:
    	info = input('>>>').encode('utf-8')
    	if len(info) == 0:continue
        client.send(info)
    	data = client.recv(1024)
        print(data)
        conn.close()
    
    #连接循环
    while TRUE:
        conn addr = server.accept()
    	# 开启线程
    	t = Thread(target = communicate,args=(conn,))
    	t.start()
    
    client

    2、进程池和线程池

    进程池和线程池介绍

    进程池和线程池都是为了减轻硬件负担,保证程序的运行,相对减少的运行速度

    1 模块导入:
    	from concurrent.futuers import ThreadPoolExecutor,ProcessPoolExecutor
    2 实例化:
    #在不知道参数的情况下,默认为当前计算机的cpu个数*5
    	线程池:pool = ThreadpoolExecutor(N)
        进程池:pool = ProcesspoolExecutor(N)
    3 提交任务
    	pool.submit()
      提交任务的两种方式:
    	① 同步:提交任务后,原地等待任务的返回结果,再执行下一步代码
    	② 异步:提交任务后,不等待任务返回结果(通过回调函数拿到返回值),直接进下一步代码
    4 回调函数:add_done_call()
    	异步提交后一旦任务有返回结果自定交给另外一个去执行
    5 pool.shutdown:
        关闭池子,并且等待池子中所有的任务运行完毕

    例子

    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    import time
    import os
    
    
    pool = ProcessPoolExecutor(5)
    # pool = ThreadPoolExecutor(5)
    
    def task(n):
        print(n,os.getpid())
        time.sleep(2)
        return n**2
    
    def call_back(n):
        print('拿到结果:%s'%n.result())
    
    if __name__ == '__main__':
        t_list = []
        for i in range(20):
            # 回调函数,异步提交任务
            future = pool.submit(task,i).add_done_callback(call_back)
            t_list.append(future)
            pool.shutdown()
            for p in t_list:
                print(">>>",p.result())
        print('主')
    
    
    
    进程池和线程池使用

    3、协程

         1、进程:资源单位

         2、线程:执行单位

         3、协程:单线程下实现并

         4、协程是技术人员虚拟出来的的概念,对于操作系统并不存在

    核心:切换+保存状态 作用就是将单线程的效率提升到最高,多进程下开多线程,多线程下用协程,实现高并发

    优点:协程切换开销小,单线程内实现并发的效果,最大限度的利用cpu

    缺点:无法利用多核,一旦阻塞整个线程就会阻塞

    怎么使用

    1 导入gevent模块
    g1=gevent.spawn(func,1,,2,3,x=4,y=5)创建一个协程对象g1,spawn括号内第一个参数是函数名,如eat,后面可以有多个参数,可以是位置实参或关键字实参,都是传给函数eat的
    2 g1.join() #等待g1结束
    3 g1.value#拿到func1的返回值

    协程实现高并发:

    from gevent import monkey;monkey.patch_all()
    import socket
    from gevent import spawn
    
    def communicate(conn):
        while True:
            try:
                data = conn.recv(1024)
                if len(data)==0:break
                print(data.decode('utf-8'))
                conn.send(data.upper())
    
            except ConnectionResetError:
                break
        conn.close()
    
    def server():
        server = socket.socket()
        server.bind(('127.0.0.1',8080))
        server.listen(5)
        while True:
            conn,addr = server.accept()
            spawn(communicate,conn)
    
    if __name__ == '__main__':
        s1 = spawn(server)
        s1.join()
    
    
    server
    import socket
    from threading import Thread,current_thread
    
    def client():
        client = socket.socket()
        client.connect(('127.0.0.1',8080))
        n = 1
        while True:
            data = '%s %s'%(current_thread().name,n)
            n+=1
            client.send(data.encode('utf-8'))
            info = client.recv(1024)
            print(info)
    
    if __name__ == '__main__':
        for i in range(500):
            t = Thread(target=client)
            t.start()
    
    
        while True:
            conn,addr = server.accept()
            spawn(communicate,conn)
    
    if __name__ == '__main__':
        s1 = spawn(server)
        s1.join()
    
    client

    4 IO 模型

    ① 阻塞IO

    ② 非阻塞IO:非阻塞IO(服务端通信针对accept用s.setblocking(False)加异常捕获,cpu占用率过高)

    ③ IO多路复用:

    在只检测一个套接字的情况下,他的效率连阻塞IO都比不上。因为select这个中间人增加了环节。

    但是在检测多个套接字的情况下,就能省去wait for data过程

    ④ 异步IO

  • 相关阅读:
    UVA 11991 Easy Problem from Rujia Liu(map,vector的使用)
    UVA 11995 I Can Guess the Data Structure! (STL应用)
    HDU 2795 Billboard(线段树,单点更新)
    HDU 1394 Minimum Inversion Number (线段树,单点更新)
    UVA 11827 Maximum GCD(读入技巧,stringstream的使用)
    contest 2 总结
    Const 1 总结
    开始进行大量题目练习
    函数式线段树的个人理解
    poj 2318 TOYS
  • 原文地址:https://www.cnblogs.com/king-home/p/10839601.html
Copyright © 2011-2022 走看看