多线程 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





posted @ 2016-01-29 18:35  RootMe  阅读(372)  评论(0编辑  收藏  举报