一、IO多路复用
1、客户端
#!/usr/bin/env python #-*-coding:utf-8-*- import socket sk=socket.socket() sk.connect(('127.0.0.1',8888,)) data=sk.recv(1024) print(data) while True: inp=input('>>>') sk.sendall(bytes(inp,encoding='utf-8')) print(sk.recv(1024)) sk.close()
2、服务端
#!/usr/bin/env python #-*-coding:utf-8-*- import socket import select sk=socket.socket() sk.bind(('127.0.0.1',8888,)) sk.listen(5) inputs=[sk,] outputs=[] messages={} #del messages[张三] #message={ # 张三:[消息1,消息2] # } while True: rlist,wlist,e,=select.select(inputs,outputs,[],1) print(len(inputs),len(rlist),len(wlist),len(outputs)) #监听sk(服务器端)对象,如果sk对象发生变化,表示有客户端连接了,此时rlist值为[sk] #监听conn对象,如果conn发生变化,表示客户端有新消息发送过来了,此时rlist的值为[客户端] for r in rlist: if r==sk: #新客户来连接 conn,address=r.accept() #conn是什么?其实是socket对象 inputs.append(conn) messages[conn]=[] conn.sendall(bytes('hello',encoding='utf-8')) else: #有人给我发消息 # beta=r.recv(1024) print('==============') try: ret=r.recv(1024) if not ret: raise Exception('断开连接') else: outputs.append(r) messages[r].append(ret) except Exception as e: inputs.remove(r) del messages[r] #所有给我发过消息的人 for w in wlist: msg=messages[w].pop() resp=msg+bytes('response',encoding='utf-8') w.sendall(resp) outputs.remove(w)
二、线程
Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。
#!/usr/bin/env python # -*- coding:utf-8 -*- import threading import time def show(arg): time.sleep(1) print 'thread'+str(arg) for i in range(10): t = threading.Thread(target=show, args=(i,)) t.start() print 'main thread stop'
上述代码创建了10个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行指令。
更多方法:
- start 线程准备就绪,等待CPU调度
- setName 为线程设置名称
- getName 获取线程名称
- setDaemon 设置为后台线程或前台线程(默认)
如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止 - join 逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
- run 线程被cpu调度后自动执行线程对象的run方法
自定义类程序
import threading import time class MyThread(threading.Thread): def __init__(self,num): threading.Thread.__init__(self) self.num = num def run(self):#定义每个线程要运行的函数 print("running on number:%s" %self.num) time.sleep(3) if __name__ == '__main__': t1 = MyThread(1) t2 = MyThread(2) t1.start() t2.start()
线程锁(Lock、RLock)
由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,当多个线程同时修改同一条数据时可能会出现脏数据,所以,出现了线程锁 - 同一时刻允许一个线程执行操作。
未用锁:
#!/usr/bin/env python # -*- coding:utf-8 -*- import threading import time gl_num = 0 def show(arg): global gl_num time.sleep(1) gl_num +=1 print gl_num for i in range(10): t = threading.Thread(target=show, args=(i,)) t.start() print 'main thread stop'
#!/usr/bin/env python #coding:utf-8 import threading import time gl_num = 0 lock = threading.RLock() def Func(): lock.acquire() global gl_num gl_num +=1 time.sleep(1) print gl_num lock.release() for i in range(10): t = threading.Thread(target=Func) t.start()