python多线程编程

原创 2015年11月17日 21:06:33

python提供了几个用于多线程编程的模块,thread,threading,Queue等。其中thread模块提供了基本的线程和锁的支持,threading提供了更高级别的功能,Queue模块允许用户创建一个可以用于多个线程之间共享数据的队列数据结构。
因为thread有下面几个缺点,所以建议使用threading模块:
1.threading更为先进
2.thread模块的同步原语很少
3.当主线程结束时所有的线程都会被强制结束,没有警告也没有正常的清理工作
4.不支持守护线程,也就是不能设置线程为daemon
所以下面重点介绍threading的三种创建进程的方法。

  1. 创建一个Thread实例,传给他一个函数
import threading
from time import ctime,sleep

loops=[4,2]
def loop(nloop,nsecond):
    print('start loop ',nloop,'at: ',ctime())
    sleep(nsecond)
    print('loop ',nloop,' done at: ',ctime())
def main():
    print('starting at: ',ctime())
    threads=[]
    nloops=range(len(loops))

    for i in nloops:
        #'target','args' are must
        threads.append(threading.Thread(target=loop,args=(i,loops[i])))
    for i in nloops:
        threads[i].start()

    for i in nloops:
        threads[i].join()
    print('all DONE at: ',ctime())
if __name__=='__main__':
    main()
  1. 创建一个Thread实例,传给他一个可调用的类对象

其中这个类对象要是可调用的对象,也就是实现了call函数的类

import threading
from time import ctime,sleep

loops=[4,2]

class ThreadFunc():
    def __init__(self,func,args,name=''):
        self.name=name
        self.func=func
        self.args=args
    def __call__(self):
        self.func(*self.args)

def loop(nloop,nsecond):
    print('start loop ',nloop,'at: ',ctime())
    sleep(nsecond)
    print('loop ',nloop,' done at: ',ctime())
def main():
    print('starting at: ',ctime())
    threads=[]
    nloops=range(len(loops))

    for i in nloops:
        threads.append(threading.Thread(target=ThreadFunc(loop,(i,loops[i]),loop.__name__)))
    for i in nloops:
        threads[i].start()

    for i in nloops:
        threads[i].join()
    print('all DONE at: ',ctime())
if __name__=='__main__':
    main()

3.从Thread派生出一个子类,创建一个子类的实例
(1)这个子类的构造器要先调用基类的构造器;(2)子类要实现run函数

import threading
from time import ctime,sleep

class MyThread(threading.Thread):
    def __init__(self,func,args,name=""):
        threading.Thread.__init__(self)
        self.name=name
        self.func=func
        self.args=args
        self.res=0
    def getResult(self):
        return self.res
    def run(self):
        print('starting ',self.name,'at: ',ctime())
        self.res=self.func(*self.args)
        print(self.name,' finished at: ',ctime())
def Fib(n):
    sleep(0.005)
    if n<2:return 1
    return Fib(n-1)+Fib(n-2)
def Fac(n):
    sleep(0.1)
    if n<2:return 1
    return n*Fac(n-1)
def Sum(n):
    sleep(0.1)
    if n<1:return 0
    return n+Sum(n-1)

func=[Fib,Fac,Sum]
n=12
def main():
    threads=[]
    nfunc=range(len(func))

    print('***MULTIPE THREAD')
    for i in nfunc:
       threads.append(MyThread(func[i],(n,),func[i].__name__))

    for i in nfunc:
        threads[i].start()
    for i in nfunc:
        threads[i].join()
        print(threads[i].getResult())
    print('all DONE')
if __name__=='__main__':
    main()

下面是queue模块,它提供了三个类,Queue,LifoQueue,PriorityQueue
具体详见:Python queue模块
其中的两个方法:
put(item,block=0)如果block不等于0,函数会一直阻塞下去到队列中有空间为止
get(block=0)block的作用同put

import threading
from time import ctime,sleep
from queue import Queue
from random import randint


class MyThread(threading.Thread):
    def __init__(self,func,args,name=""):
        threading.Thread.__init__(self)
        self.name=name
        self.func=func
        self.args=args
        self.res=0
    def getResult(self):
        return self.res
    def run(self):
        print('starting ',self.name,'at: ',ctime())
        self.res=self.func(*self.args)
        print(self.name,' finished at: ',ctime())

def writeQ(queue):
    print('producting object for Q...')
    queue.put('xxx',1)
    print('size now',queue.qsize())

def readQ(queue):
    val=queue.get(1)
    print('consumed object from Q...size now',queue.qsize())
def writer(queue,loops):
    for i in range(loops):
        writeQ(queue)
        sleep(randint(1,3))
def reader(queue,loops):
    for i in range(loops):
        readQ(queue)
        sleep(randint(2,5))

func=[writer,reader]
n=12
def main():
    threads=[]
    nfunc=range(len(func))
    q=Queue(32)
    nloops=randint(2,5)

    print('***MULTIPE THREAD')
    for i in nfunc:
       threads.append(MyThread(func[i],(q,nloops),func[i].__name__))

    for i in nfunc:
        threads[i].start()
    for i in nfunc:
        threads[i].join()
    print('all DONE')
if __name__=='__main__':
    main()

然后简单的介绍一下threading中的另外三个类Lock,Condition,Event。
Lock:
其实很简单就是加锁控制资源访问

import threading
import time

class MyThread(threading.Thread):
    def run(self):
        global num
        time.sleep(1)

        if mutex.acquire(1): 
            num = num+1
            msg = self.name+' set num to '+str(num)
            print(msg)
            mutex.release()
num = 0
mutex = threading.Lock()
def test():
    for i in range(5):
        t = MyThread()
        t.start()
if __name__ == '__main__':
    test()

Evevt类:
多个线程等待某个事件发生,发生后,所有的线程被激活
Event对象实现了简单的线程通信机制,它提供了设置信号,清楚信号,等待等用于实现线程间的通信。
1 设置信号
使用Event的set()方法可以设置Event对象内部的信号标志为真。Event对象提供了isSet()方法来判断其内部信号标志的状态。当使用event对象的set()方法后,isSet()方法返回真
2 清除信号
使用Event对象的clear()方法可以清除Event对象内部的信号标志,即将其设为假,当使用Event的clear方法后,isSet()方法返回假
3 等待
Event对象wait的方法只有在内部信号为真的时候才会很快的执行并完成返回。当Event对象的内部信号标志位假时,则wait方法一直等待到其为真时才返回。

import threading
class mythread(threading.Thread):
    def __init__(self,threadname):
        threading.Thread.__init__(self,name=threadname)
    def run(self):
        global event
        if event.isSet():
            event.clear()
            event.wait()
            print(self.getName())
        else:
            print(self.getName())
            event.set()
event=threading.Event()
event.set()
t1=[]
for i in range(10):
    t=mythread(str(i))
    t1.append(t)
for i in t1:
    i.start()

Condition类:
使用Condition对象可以在某些事件触发或者达到特定的条件后才处理数据,Condition除了具有Lock对象的acquire方法和release方法外,还有wait方法、notify方法、notifyAll方法等用于条件处理。

threading.Condition([lock]):创建一个condition,支持从外界引用一个Lock对象(适用于多个condtion共用一个Lock的情况),默认是创建一个新的Lock对象。

acquire()/release():获得/释放 Lock

wait([timeout]):线程挂起,直到收到一个notify通知或者超时(可选的,浮点数,单位是秒s)才会被唤醒继续运行。wait()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。调用wait()会释放Lock,直至该线程被Notify()、NotifyAll()或者超时线程又重新获得Lock.

notify(n=1):通知其他线程,那些挂起的线程接到这个通知之后会开始运行,默认是通知一个正等待该condition的线程,最多则唤醒n个等待的线程。notify()必须在已获得Lock前提下才能调用,否则会触发RuntimeError。notify()不会主动释放Lock。

notifyAll(): 如果wait状态线程比较多,notifyAll的作用就是通知所有线程(这个一般用得少)

import threading 
import time 

condition = threading.Condition() 
products = 0 

class Producer(threading.Thread): 
    def __init__(self): 
        threading.Thread.__init__(self) 

    def run(self): 
        global condition, products 
        while True: 
            if condition.acquire(): 
                if products < 10: 
                    products += 1; 
                    print("Producer(%s):deliver one, now products:%s" %(self.name, products))
                    condition.notify() 
                else: 
                    print("Producer(%s):already 10, stop deliver, now products:%s" %(self.name, products))
                    condition.wait(); 
                condition.release() 
                time.sleep(2) 

class Consumer(threading.Thread): 
    def __init__(self): 
        threading.Thread.__init__(self) 

    def run(self): 
        global condition, products 
        while True: 
            if condition.acquire(): 
                if products > 1: 
                    products -= 1 
                    print("Consumer(%s):consume one, now products:%s" %(self.name, products))
                    condition.notify() 
                else: 
                    print("Consumer(%s):only 1, stop consume, products:%s" %(self.name, products))
                    condition.wait(); 
                condition.release() 
                time.sleep(2) 

if __name__ == "__main__": 
    for p in range(0, 2): 
        p = Producer() 
        p.start() 
    for c in range(0, 10): 
        c = Consumer() 
        c.start()
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

python 多线程编程

  • 2011-02-14 08:40
  • 675B
  • 下载

python多线程编程(二)--threading模块

上一篇文章讲thread模块的使用,我们接下来看threading模块怎么使用。 threading模块对象 对象 描述 Thread 一个线程的执行对象 Lock...

python多线程编程

一)线程基础 1、创建线程: thread模块提供了start_new_thread函数,用以创建线程。start_new_thread函数成功创建后还可以对其进行操作。 其函数原型...

python多线程编程(4): 死锁和可重入锁

原文转载自:http://www.cnblogs.com/holbrook/archive/2012/03/08/2385449.html 死锁 在线程间共享多个资源的时候,如果两个线程分别占...

python多线程编程基础

#coding=utf-8 import threading #导入threading包 from time import sleep #引入time包中的sleep函数,这样在函数里可以直接使用sl...

python 多线程编程(四)

一个简单的生成者消费者的例子: ''' Created on 2012-3-9 @author: Administrator ''' #!/usr/bin/env python from ran...
  • Cages
  • Cages
  • 2012-03-09 17:54
  • 719

python学习笔记——多线程编程

Python代码代码的执行由python虚拟机(也叫解释器主循环)来控制。Python在设计之初就考虑到要在主循环中,同时只有一个线程在执行,就像单CPU的系统中运行多个进程那样,内存中可以存放多个程...

python多线程编程(一)--thread模块

python提供两个模块支持多线程编程:thread和threading。 thread模块函数 函数 描述 start_new_thread(fu...

python多线程编程(5): 条件变量同步

本文转载自:http://www.cnblogs.com/holbrook/archive/2012/03/13/2394811.html 互斥锁是最简单的线程同步机制,Python提供的Condi...

Python多线程编程(一)

1. threading模块Python 实现多线程编程可以通过thread模块(thread模块在Python3中更名为_thread)或者是更高级的threading模块,这里主要讲的是threa...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)