多线程 threading
Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元。
import threading #导入多线程模块 import time def run(num): print ("thread..",num) time.sleep(1) #休眠1秒 ####单线程执行10次,需要花10秒 for n in range(10): run(n) ####多线程执行10次,则花1秒 for i in range(10): t = threading.Thread(target=run,args=(i,)) t.start()
上述代码创建了10个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行指令。
更多方法:
- start 线程准备就绪,等待CPU调度
- setName 为线程设置名称
- getName 获取线程名称
- setDaemon 设置为后台线程或前台线程(默认)
如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止 - join 逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
- run 线程被cpu调度后执行Thread类对象的run方法
自定义线程
from threading import Thread import time class MyThread(Thread): #创建一个自定义类,必须继承Thread def run(self): #创建一个run函数,来优先执行父类Thread中的run time.sleep(1) print '我是线程' #这里可以自定义加一些功能 Thread.run(self) #执行完后,再执行父类中的run() def Bar(arg): print 'bar',arg t = MyThread(target=Bar,args=(1,)) t.start() print 'end..'
线程锁
由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,CPU接着执行其他线程。所以,可能出现问题
def run(num): lock.acquire() #加锁 print("thread...",num) lock.release() #开锁 time.sleep(1) lock = threading.RLock() #线程之间加一个锁,防止线程之间输出混乱 for i in range(100): t = threading.Thread(target=run,args=(i,)) t.start()
Event
python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。
事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。
- clear:将“Flag”设置为False
- set:将“Flag”设置为True
import threading def run(event): print 'start' event.wait() #输出start后暂停 print 'stop' event_obj = threading.Event() #定义方法为event for i in range(10): t = threading.Thread(target=run,args=(event_obj,)) #循环执行run函数,参数为event_obj t.start() event_obj.clear() inp = raw_input("input:") if inp == "true": #如果输入正确,则停止阻塞 event_obj.set()
线程池
版本一:
import Queue import threading import time class ThreadPool(object): #线程池 def __init__(self, max_num): self.queue = Queue.Queue(max_num) #创建一个Queue对列,存放4个值 for i in xrange(max_num): self.queue.put(threading.Thread) #queue = 10个 threading.Thread def get_thread(self): return self.queue.get() def add_thread(self): self.queue.put(threading.Thread) pool = ThreadPool(4) #从线程池队列拿4个值, pool=threading.Thread def func(arg, p): print arg import time time.sleep(5) p.add_thread() #消耗掉一个线程,会执行add_thread(),往queue中添加一个 threading.Thread for i in xrange(20): #一共执行20个进程 thread = pool.get_thread() # 同时4个进程,超过4个会阻塞 t = thread(target=func, args=(i, pool)) t.start()
版本二:
from Queue import Queue import contextlib import threading WorkerStop = object() class ThreadPool: workers = 0 threadFactory = threading.Thread currentThread = staticmethod(threading.currentThread) def __init__(self, maxthreads=20, name=None): self.q = Queue(0) self.max = maxthreads self.name = name self.waiters = [] self.working = [] def start(self): needSize = self.q.qsize() while self.workers < min(self.max, needSize): self.startAWorker() def startAWorker(self): self.workers += 1 name = "PoolThread-%s-%s" % (self.name or id(self), self.workers) newThread = self.threadFactory(target=self._worker, name=name) newThread.start() def callInThread(self, func, *args, **kw): self.callInThreadWithCallback(None, func, *args, **kw) def callInThreadWithCallback(self, onResult, func, *args, **kw): o = (func, args, kw, onResult) self.q.put(o) @contextlib.contextmanager def _workerState(self, stateList, workerThread): stateList.append(workerThread) try: yield finally: stateList.remove(workerThread) def _worker(self): ct = self.currentThread() o = self.q.get() while o is not WorkerStop: with self._workerState(self.working, ct): function, args, kwargs, onResult = o del o try: result = function(*args, **kwargs) success = True except: success = False if onResult is None: pass else: pass del function, args, kwargs if onResult is not None: try: onResult(success, result) except: #context.call(ctx, log.err) pass del onResult, result with self._workerState(self.waiters, ct): o = self.q.get() def stop(self): while self.workers: self.q.put(WorkerStop) self.workers -= 1 """ def show(arg): import time time.sleep(1) print arg pool = ThreadPool(20) for i in range(500): pool.callInThread(show, i) pool.start() pool.stop() """
更多参见:twisted.python.threadpool
上下文管理:https://docs.python.org/2/library/contextlib.html