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