1.基于多线程实现套接字服务端支持并发

服务端

from socket import *
from threading import Thread

def comunicate(conn):
    while True:  # 通信循环
        try:
            data = conn.recv(1024)
            if len(data) == 0: break
            conn.send(data.upper())
        except ConnectionResetError:
            break
    conn.close()

def server(ip, port, backlog=5):
    server = socket(AF_INET, SOCK_STREAM)
    server.bind((ip, port))
    server.listen(backlog)

    while True:  # 链接循环
        conn, client_addr = server.accept()
        print(client_addr)

        # 通信
        t=Thread(target=comunicate,args=(conn,))
        t.start()

if __name__ == '__main__':
    s=Thread(target=server,args=('127.0.0.1',8081))
    s.start()

客户端

from socket import *

client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8081))

while True:
    msg=input('>>: ').strip()
    if len(msg) == 0:continue
    client.send(msg.encode('utf-8'))
    data=client.recv(1024)
    print(data.decode('utf-8'))

2.进程池

使用进程池就是对启动进程数加以限制

from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
import time,random,os

def task(name,n):
    print('%s%s is running'%(name,os.getpid()))
    time.sleep(random.randint(1,3))
    return n

if __name__ == '__main__':
    # print(os.cpu_count())#打印cpu核数
    p=ProcessPoolExecutor(4)#进程池预留了4个进程,可以提供开启。后续一次性可以同时开启4个进程,进程号不会变。
    # 如果不传参数(数字),那么默认最多开启的进程数为电脑的核数
    l=[]
    for i in range(20):
        #同步提交
        # res=p.submit(task,'进程pid:').result()
        # print(res)
        #异步提交
        future=p.submit(task,'进程pid:',i)#submit是异步提交,直接传位置参数,或关键字参数
        l.append(future)
    p.shutdown(wait=True)#关闭进程池的入口,并且在原地等待进程池内所有任务运行完毕
    for future in l:
        print(future.result())
    print('主')

不使用回调函数进行异步提交,自行解析

import time, os, random
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import Thread
import requests

def get(url):
    print('%s GET %s' % (os.getpid(), url))
    time.sleep(random.randint(1, 3))
    response = requests.get(url)
    if response.status_code == 200:
        return response.text
    else:
        return '下载失败'

def parse(res):
    print('%s解析结果为%s' % (os.getpid(), len(res)))

if __name__ == '__main__':
    urls = [
        'https://www.baidu.com',
        'https://www.sina.com.cn',
        'https://www.tmall.com',
        'https://www.jd.com',
        'https://www.python.org',
        'https://www.bilibili.com',
        'https://www.youku.com',
        'https://www.baidu.com',
        'https://www.baidu.com',
        'https://www.baidu.com',
    ]
    p = ProcessPoolExecutor(4)
    l = []
    for url in urls:
        future = p.submit(get, url)
        l.append(future)
    p.shutdown(wait=True)
    for future in l:
        res = future.result()
        parse(res)
    print('主')

异步一般与回调函数连用

使用回调函数

import time, os, random
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import Thread
import requests

def get(url):
    print('%s GET %s' % (os.getpid(), url))
    time.sleep(random.randint(1, 3))
    response = requests.get(url)
    if response.status_code == 200:
        return response.text
    else:
        return '下载失败'

def parse(res):
    res=res.result()
    print('%s解析结果为%s' % (os.getpid(), len(res)))

if __name__ == '__main__':
    urls = [
        'https://www.baidu.com',
        'https://www.sina.com.cn',
        'https://www.tmall.com',
        'https://www.jd.com',
        'https://www.python.org',
        'https://www.bilibili.com',
        'https://www.youku.com',
        'https://www.baidu.com',
        'https://www.baidu.com',
        'https://www.baidu.com',
    ]
    p = ProcessPoolExecutor(4)
    start=time.time()
    for url in urls:
        future = p.submit(get, url)
        future.add_done_callback(parse)#parse会在任务完毕后触发,然后接收一个参数future对象
    p.shutdown(wait=True)
    print(time.time()-start)
    print('主%s'%os.getpid())

使用线程池开多线程进行任务

线程池和进程池的用法很相似

import time, os, random
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import Thread,current_thread
import requests

def get(url):
    print('%s GET %s' % (current_thread().name, url))
    time.sleep(random.randint(1, 3))
    response = requests.get(url)
    if response.status_code == 200:
        return response.text
    else:
        return '下载失败'

def parse(res):
    res=res.result()
    print('%s解析结果为%s' % (current_thread().name, len(res)))

if __name__ == '__main__':
    urls = [
        'https://www.baidu.com',
        'https://www.sina.com.cn',
        'https://www.tmall.com',
        'https://www.jd.com',
        'https://www.python.org',
        'https://www.bilibili.com',
        'https://www.youku.com',
        'https://www.baidu.com',
        'https://www.baidu.com',
        'https://www.baidu.com',
    ]
    p = ThreadPoolExecutor(4)
    start=time.time()
    for url in urls:
        future = p.submit(get, url)
        future.add_done_callback(parse)#parse会在任务完毕后触发,然后接收一个参数future对象
        #如果开启的是进程,那么来干parse这件事的是主进程
        #如果开启的是线程,那么线程池里的线程也可以来做parse,谁有空谁做
    p.shutdown(wait=True)
    print(time.time()-start)
    print('主%s'%current_thread().name)

3.协程

使用协程的目标是想要在单线程下实现并发

实现协程的原理是:切换+保存状态

注意:协程是程序员意淫出来的东西,操作系统里只有进程和线程的概念。

在单线程下实现多个任务间遇到IO就切换可以降低单线程的IO时间,从而最大限度地提升单线程的效率。

不遇到IO就进行切换的话并不能提升单线程的效率,这样不算是成功的协程。

4.gevent

要实现单线程下的协程,需要gevent模块

from gevent import spawn,sleep
from gevent import monkey,joinall
monkey.patch_all()#这样gevent就能识别所有IO行为
import time

#gevent不能识别本身以外的IO行为,为了监听所有的IO行为,要导入monkey
def play(name):
    print('%s play1'%name)
    time.sleep(3)
    print('%s play2'%name)
def eat(name):
    print('%s eat1'%name)
    time.sleep(5)
    print('%s eat2'%name)

start=time.time()
g1=spawn(play,'刘清正')#这里是异步提交
g2=spawn(eat,'刘清正')

joinall([g1,g2])
stop=time.time()
print(stop-start)

5.单线程实现并发套接字

进程池线程池 协程 gvent 单线程实现并发套接字的更多相关文章

  1. python 进程、线程与协程的区别

    进程.线程与协程区别总结 - 1.进程是计算器最小资源分配单位 - 2.线程是CPU调度的最小单位 - 3.进程切换需要的资源很最大,效率很低 - 4.线程切换需要的资源一般,效率一般(当然了在不考虑 ...

  2. 三、进程和线程、协程在python中的使用

    三.进程和线程.协程在python中的使用 1.多进程一般使用multiprocessing库,来利用多核CPU,主要是用在CPU密集型的程序上,当然生产者消费者这种也可以使用.多进程的优势就是一个子 ...

  3. 图解Python 【第八篇】:网络编程-进程、线程和协程

    本节内容一览图: 本章内容: 同步和异步 线程(线程锁.threading.Event.queue 队列.生产者消费者模型.自定义线程池) 进程(数据共享.进程池) 协程 一.同步和异步 你叫我去吃饭 ...

  4. python基础之进程、线程、协程篇

    一.多任务(多线程) 多线程特点:(1)线程的并发是利用cpu上下文的切换(是并发,不是并行)(2)多线程执行的顺序是无序的(3)多线程共享全局变量(4)线程是继承在进程里的,没有进程就没有线程(5) ...

  5. python并发编程之进程、线程、协程的调度原理(六)

    进程.线程和协程的调度和运行原理总结. 系列文章 python并发编程之threading线程(一) python并发编程之multiprocessing进程(二) python并发编程之asynci ...

  6. Python3 进程、线程和协程

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 进程.线程和协程的对比 1.定义对比 进程:是系统进行资源分配的基本单位,每启动一个进程,操作系统都需要为其分配运 ...

  7. 协程、gevent实现异步io、进程、线程、协程对比

    异步io的说白了就是遇到io操作的时候,就停下来去做别的事情.io分网络io和磁盘io,网络io比如说打开一个网站获取数据,下载一首歌等等,磁盘io就是把数据存到一个文件里面,写到磁盘上. 从网站上获 ...

  8. Python进程、线程、协程及IO多路复用

    详情戳击下方链接 Python之进程.线程.协程 python之IO多路复用

  9. 进程、线程、协程和GIL(二)

    上一篇博客讲了进程.线程.协程和GIL的基本概念,这篇我们来说说在以下三点: 1> python中使用threading库来创建线程的两种方式 2> 使用Event对消来判断线程是否已启动 ...

随机推荐

  1. UILabel(富文本)

    本文转载至 http://www.jianshu.com/p/5d24d22f99c3 富文本 NSString *str = @"人生若只如初见,何事秋风悲画扇.\n等闲变却故人心,却道故 ...

  2. 跟bWAPP学WEB安全(PHP代码)--终结篇:文件目录遍历、文件上传、SSRF、CSRF、XXE、文件包含

    前言 过年过的很不顺,家里领导和我本人接连生病,年前腊月29才都治好出院,大年初六家里的拉布拉多爱犬又因为细小医治无效离开了,没能过年回家,花了好多钱,狗狗还离世了.所以也就没什么心思更新博客.今天初 ...

  3. 还有看不懂的java语句?

    Person stuProxy= (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[] ...

  4. IBatisNet不常用到的配置(Dao.config ConnectionTimeout),居然不起作用(前辈留给我们的坑)

    IBattis 默认超时时间好像是30s,可多于这个时间总就会报错:DaoProxy : unable to intercept method name 'ExcuteQuery', cause : ...

  5. .NET Core开发日志——Model Binding

    ASP.NET Core MVC中所提供的Model Binding功能简单但实用,其主要目的是将请求中包含的数据映射到action的方法参数中.这样就避免了开发者像在Web Forms时代那样需要从 ...

  6. {Django基础十之Form和ModelForm组件}一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 ModelForm

    Django基础十之Form和ModelForm组件 本节目录 一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 Model ...

  7. {MySQL存储引擎介绍}一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用

    MySQL存储引擎介绍 MySQL之存储引擎 本节目录 一 存储引擎解释 二 MySQL存储引擎分类 三 不同存储引擎的使用 一 存储引擎解释 首先确定一点,存储引擎的概念是MySQL里面才有的,不是 ...

  8. 更新快排中的partition

    这一次是将partition 过程中, 维护三个区域. <x   =x  >x  三区域. 还有个待定的区域. /* * 将数组划分为三个分区, 小于arr[R], 等于arr[R], 大 ...

  9. [No000016A]CSS常用三种选择器

    1.HTML Tag p{color:red;} 2.id #myid{color:red;} 3.class .myclass{color:red;} CSS常用文本样式属性 color font- ...

  10. 一个列转行SQL示例(wm_concat函数和replace函数合用)

    准备测试数据: create table test01( groupid      number, a            number, b            number, c        ...