本篇博文参考:
http://www.cnblogs.com/jishuweiwang/p/5660933.html
http://www.cnblogs.com/wupeiqi/articles/5040823.html
概述
默认应用程序:是单进程、单线程的。
进程是资源分配的最小单位。与程序相比,程序只是一组指令的有序集合,它本身没有任何运行的含义,只是一个静态实体。进程是程序在某个数据集上 的执行,是一个动态实体。它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而被撤消,反映了一个程序在一定的数据集上运行的 全部动态过程。每个正在系统上运行的程序都是一个进程。每个进程包含一到多个线程。进程也可能是整个程序或者是部分程序的动态执行。
线程是轻量级的进程或子进程,是CPU调度的最小单位,所有的线程都存在于相同的进程。所以线程基本上是轻量级的进程,它负责在单个程序里执行 多任务。通常由操作系统负责多个线程的调度和执行。多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。
由于Python中GIL的存在,GIL 会在进程级别加的一个逻辑锁,这个锁粒度很大,把整个系统资源看做一个整体,所以GIL 不管你有多少CPU核心,都看做一个CPU核心来用,虽然单进程多线程的程序拥有多个线程,但是同一时间之会有一个线程利用到CPU资源。因此为了提高 CPU利用率,通常会启用多进程,即启动多个Python进程来提高CPU的利率用,从而提高工作效率。
对比
|
对比维度 |
多进程 |
多线程 |
总结 |
|
数据共享、同步 |
数据共享复杂,需要用IPC;数据是分开的,同步简单 |
因为共享进程数据,数据共享简单,但也是因为这个原因导致同步复杂 |
各有优势 |
|
内存、CPU |
占用内存多,切换复杂,CPU利用率低 |
占用内存少,切换简单,CPU利用率高 |
线程占优 |
|
创建销毁、切换 |
创建销毁、切换复杂,速度慢 |
创建销毁、切换简单,速度很快 |
线程占优 |
|
编程、调试 |
编程简单,调试简单 |
编程复杂,调试复杂 |
进程占优 |
|
可靠性 |
进程间不会互相影响 |
一个线程挂掉将导致整个进程挂掉 |
进程占优 |
|
分布式 |
适应于多核、多机分布式;如果一台机器不够,扩展到多台机器比较简单 |
适应于多核分布式 |
进程占优 |
选用
单进程,多线程的程序(io操作不占用CPU):如果是CPU密集型,那么则不能提高效率。如果是IO密集型,那么则能提高效率。
多进程,单线程的程序:CPU密集型的,一般用多进程提高并发效率。
小结:
CPU密集型:多进程
IO密集型:多线程
ThreadingTCPServer
socketserver内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理多个客户端请求的Socket服务端。即:每个客户端请求连接到服务器时,Socket服务端都会在服务器是创建一个“线程”或者“进程” 专门负责处理当前客户端的所有请求。
ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个 “线程”,该线程用来和客户端进行交互。
ThreadingTCPServer基础
使用ThreadingTCPServer:
- 创建一个继承自 SocketServer.BaseRequestHandler 的类
- 类中必须定义一个名称为 handle 的方法
- 启动ThreadingTCPServer
#!/usr/bin/env python # -*- coding:utf-8 -*- # Auther: pangguoping import socketserver class MyServer(socketserver.BaseRequestHandler): def handle(self): #print self.request , self.client_address,self.server conn = self.request conn.sendall(bytes('欢迎致电10086,请输入1xxx,0转人工服务',encoding='utf-8')) Flag = True while Flag: data = conn.recv(1024) print(str(data.decode())) if str(data.decode()) == 'exit': Flag = False elif str(data.decode()) == '0': conn.sendall(bytes('通过可能会被录音',encoding='utf-8')) else: conn.sendall(bytes('请重新输入',encoding='utf-8')) if __name__ == '__main__': server = socketserver.ThreadingTCPServer(('127.0.0.1',8090),MyServer) server.serve_forever()