Python用GIL( global Interpretor Lock)和队列模型来处理资源的抢占问题,Python解释器不是线程安全的,需要持有这个锁,才可以安全访问python对象,因此,python不能很好的利用多CPU资源。
上一篇文章中讲了进程了,那么为什么还需要多线程呢,由于进程开销大,通信麻烦,所以需要多线程,多线程是在单独的进程中并发的执行任务。
线程状态:就绪 运行 休眠 中止
使用start_new_thread(func,(args1,args2...))
start_new_thread此方法接收一个函数作为参数,并启动一个线程。 已经不推荐使用thread模块了。
import threading,time class ThreadDemo(threading.Thread): def __init__(self,index,create_time): threading.Thread.__init__(self) self.index = index self.create_time = create_time def run(self): time.sleep(1) print (time.time()-self.create_time),"\t",self.index print "Thread %d exit" % (self.index) for x in range(5): t = ThreadDemo(x,time.time()) t.start()
start run join setDaemon isDaemon 注意start 和run 的区别
import threading,time,random class ThreadLocal(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.local = threading.local() def run(self): time.sleep(random.random()) self.local.numbers = [] for i in range(10): self.local.numbers.append(random.choice(range(10))) print threading.currentThread,self.local.numbers for x in range(5): t = ThreadLocal() t.start()
import threading class Counter: def __init__(self): self.value = 0 def increase(self): self.value += 1 return self.value counter = Counter() class ThreadDemo(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): print counter.increase() for x in range(100): t = ThreadDemo() t.start()结果基本都小于100,需要使用一些措施来避免出现这种问题。
import threading,thread class Counter: def __init__(self): self.value = 0 self.lock = thread.allocate_lock() def increase(self): self.lock.acquire() self.value += 1 self.lock.release() return self.value counter = Counter() class ThreadDemo(threading.Thread): def __init__(self): threading.Thread.__init__(self) def run(self): print counter.increase() for x in range(100): t = ThreadDemo() t.start()
from threading import Thread,Condition,currentThread import time,random class Producer(Thread): def __init__(self,condition,goods): Thread.__init__(self) self.cond=condition self.goods=goods def run(self): while 1: self.cond.acquire() self.goods.append(chr(random.randint(97, 122))) print self.goods cond.notifyAll() cond.release() time.sleep(random.choice(range(3))) class Consumer(Thread): def __init__(self,condition,goods): Thread.__init__(self) self.cond=condition self.goods=goods def run(self): while 1: cond.acquire() while not goods: print "has no good,wait..." cond.wait() print "consume:",goods.pop(0) print self.goods cond.release() time.sleep(random.choice(range(2))) goods=[] cond=Condition() p = Producer(cond,goods) c = Consumer(cond,goods) p.start() c.start()这里假定池子没有上限,生产者可以一直生产,消费者必须池子里有东西才能消费,为空时候等待wait. 这里与JAVA思路相同,区别就是不需要自己写一个同步的池子,反正锁都是全局锁。
# queue_example.py from Queue import Queue import threading import random import time # Producer thread class Producer(threading.Thread): def __init__(self, threadname, queue): threading.Thread.__init__(self, name = threadname) self.sharedata = queue def run(self): for i in range(20): print self.getName(),'adding',i,'to queue' self.sharedata.put(i) time.sleep(random.randrange(2)) print self.getName(),'Finished' # Consumer thread class Consumer(threading.Thread): def __init__(self, threadname, queue): threading.Thread.__init__(self, name = threadname) self.sharedata = queue def run(self): for i in range(20): print self.getName(),'got a value:',self.sharedata.get() time.sleep(random.randrange(4)) print self.getName(),'Finished' # Main thread def main(): queue = Queue(2) producer = Producer('Producer', queue) consumer = Consumer('Consumer', queue) print 'Starting threads ...' producer.start() consumer.start() producer.join() consumer.join() print 'All threads have terminated.' if __name__ == '__main__': main()