【第22期】观点:IT 行业加班,到底有没有价值?

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多线程编程总结

注:此文除了例子和使用心得是自己写的,很多都是Python核心编程中的原文。原文文风应该能看出来,就不每个地方单独表明出处了。     线程(有时被称为轻量级进程)跟进程有些相似,不同的是,所有...

Python多线程编程及同步处理

Python多线程编程,当程序需要同时并发处理多个任务时,就需要要使用多线程编程。继承线程类threading.thread,再重载成员函数run,程序处理的代码写在函数run中,最后再调用start...
  • bb6lo
  • bb6lo
  • 2015-11-28 11:16
  • 200

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

python多线程编程

python的多线程模块threading已经线程之间的通信

python3 多线程编程

0.什么是线程 1. 多线程模块 2. 创建线程的方法 3. join()方法 4.isAlive()方法 5. name属性和daemon属性 6.线程的同步---锁 7.线程的同步-...

[python] 专题八.多线程编程之thread和threading

就个人而言,学了这么多年的课程又写了这么多年的程序,虽然没有涉及到企业级的项目,但还是体会到了有几个知识点是非常重要的,包括:面向对象的思想、如何架构一个项目、设计模式来具体解决问题、应用机器学习和深...

python学习——多线程

多任务可以由多进程完成,也可以由一个进程内的多线程完成。 我们前面提到了进程是由若干线程组成的,一个进程至少有一个线程。 由于线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线...

Python多线程编程

原文 运行几个线程和同时运行几个不同的程序类似,它有以下好处:  一个进程内的多个线程和主线程分享相同的数据空间,比分开不同的过程更容易分享信息或者彼此通信。  线程有时叫做轻量化过程,而且他们不...

python 多线程编程

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

Python多线程与多进程

查看原文:http://www.wyblog.cn/2016/12/05/python%e5%a4%9a%e7%ba%bf%e7%a8%8b%e4%b8%8e%e5%a4%9a%e8%bf%9b%e7...

python多线程编程的整理perfect

多线程,海词翻译为multithreading,就是在一个进程中开启多个线程,而后线程之间可以独立运行自己的任务,而不互相干扰。在python中有thread,threading模块可以实现多线程。从...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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