线程
多进程和多线程选择
一般来说IO密集型用线程(python中线程无法夸cpu执行,i在IO操作只会少许占用cpu,线程安全),计算密集型用多进程(多进程可以跑在不同cpu上)。线程带GIL锁,同时操作IO时候只有一个可以成功操作。
多进程和线程开多少合适? 理论上多进程个数可以等于cpu核数,线程数量看业务而定,cpu在线程上切换也会占用时间(上下文切换)
thread方法说明
t.start() : 激活线程,
t.getName() : 获取线程的名称
t.setName() : 设置线程的名称
t.name : 获取或设置线程的名称
t.is_alive() : 判断线程是否为激活状态
t.isAlive() :判断线程是否为激活状态
t.setDaemon() 设置为后台线程或前台线程(默认:False);通过一个布尔值设置线程是否为守护线程,必须在执行start()方法之后才可以使用。如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止;如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
t.isDaemon() : 判断是否为守护线程
t.ident :获取线程的标识符。线程标识符是一个非零整数,只有在调用了start()方法之后该属性才有效,否则它只返回None。
t.join() :逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
t.run() :线程被cpu调度后自动执行线程对象的run方法
简单线程操作
1 #-*- coding:utf-8 -*- 2 import time 3 import threading 4 5 6 def f0():pass 7 8 9 def f1(*args): 10 time.sleep(10) 11 f0() 12 13 #线程执行前准备 14 t= threading.Thread(target=f1,args=(111,222)) 15 #开始执行线程 16 t.start() 17 18 19 t= threading.Thread(target=f1,args=(111,222)) 20 t.start() 21 t= threading.Thread(target=f1,args=(111,222)) 22 t.start()
线程锁
我们使用线程对数据进行操作的时候,如果多个线程同时修改某个数据,可能会出现不可预料的结果,为了保证数据的准确性,引入了锁的概念。
1 #-*- coding:utf-8 -*- 2 import threading 3 import time 4 5 globals_num = 0 6 7 lock = threading.RLock() 8 9 def Func(): 10 lock.acquire() # 获得锁 11 global globals_num 12 globals_num += 1 13 time.sleep(1) 14 print(globals_num) 15 lock.release() # 释放锁 16 17 for i in range(10): 18 t = threading.Thread(target=Func) 19 t.start()
threading.RLock和threading.Lock 的区别
RLock允许在同一线程中被多次acquire。而Lock却不允许这种情况。 如果使用RLock,那么acquire和release必须成对出现,即调用了n次acquire,必须调用n次的release才能真正释放所占用的琐。
线程之间通知(Event)
Event是线程间通信最间的机制之一:一个线程发送一个event信号,其他的线程则等待这个信号。用于主线程控制其他线程的执行。 Events 管理一个flag,这个flag可以使用set()设置成True或者使用clear()重置为False,wait()则用于阻塞,在flag为True之前。flag默认为False。
- Event.wait([timeout]) : 堵塞线程,直到Event对象内部标识位被设为True或超时(如果提供了参数timeout)。
- Event.set() :将标识位设为Ture
- Event.clear() : 将标识位设为False。
- Event.isSet() :判断标识位是否为Ture。
1 #-*- coding:utf-8 -*- 2 import threading 3 4 def do(event): 5 print('start') 6 #线程在这里阻塞了。等待event_obj.set()方法才能继续执行线程 7 event.wait() 8 print('execute') 9 10 event_obj = threading.Event() 11 for i in range(10):#加锁 12 t = threading.Thread(target=do,args=(event_obj,)) 13 t.start() 14 15 #event_obj.clear()设置为flase 线程就阻塞了。 16 event_obj.clear() 17 18 inp = raw_input('input:')#放锁 19 print(inp) 20 if inp == 'true': 21 #发送event事件,线程有阻塞变成无阻塞 22 event_obj.set()