• 2016/1/3 Python中的多线程(2):threading模块


    之前提了Python多线程的一点使用,今天介绍更好的threading模块,它提供了Thread类和一些比较好用的同步机制。

    先介绍Thread类

    threading模块中的Thread类有很多thread模块里没有的方法,一般使用时可以选择几种方法里的一种:

    • 创建一个Thread实例,传给它一个函数;
    • 创建一个Thread实例,传给它一个可调用的类对象;
    • 从Thread派生一个子类,创建这个子类的实例。

    可以看看它有哪些方法

    函数 描述
    start() 开始线程的执行

    run()

    定义线程的功能的函数(一般会被子类重写)
    join(timeout=None) 程序挂起,知道线程结束,如果给了timeout,最多阻塞timeout秒

    getName()

    返回线程的名字
    setName(name) 设置线程的名字
    isAlive() 布尔标志,表示这个线程是否还在运行中
    isDaemon() 返回线程的daemon标志
    setDaemon(daemonic) 把线程的daemon标志设置成daemonic

    用threading模块重写我们上次的例子:

    import threading
    from time import sleep, ctime
    
    loops = [4, 2]
    
    def loop(nloop, nsec):
        print 'start loop%s at: %s
    ' % (nloop, ctime()),
        sleep(nsec)
        print 'loop%s done at: %s
    ' % (nloop, ctime()),
    
    def main():
        print 'starting at: %s
    ' % ctime(),
        threads = []
        nloops = range(len(loops))
    
        for i in nloops:
            t = threading.Thread(target = loop,
                                 args=(i,loops[i]))
            threads.append(t)
    
        for i in nloops:
            threads[i].start()
    
        for i in nloops:
            threads[i].join()
        print 'all DONE at: %s
    ' %ctime(),
    
    if __name__ == '__main__':
        main()

    结果也是如下显示:

    >>> 
    starting at: Sun Jan 03 11:37:43 2016
    start loop0 at: Sun Jan 03 11:37:43 2016
    start loop1 at: Sun Jan 03 11:37:43 2016
    loop1 done at: Sun Jan 03 11:37:45 2016
    loop0 done at: Sun Jan 03 11:37:47 2016
    all DONE at: Sun Jan 03 11:37:47 2016

     比起昨天的锁,这里只需要简单地对每个线程使用join()函数就可以了。

    join()看上去会比一个等待锁释放的无限循环清楚一些。它另一个很重要的方面是可以完全不用调用,一旦线程启动后就会一直执行,知道线程的函数结束退出位置。

    上面使用的是一种传递函数给Thread模块,也可以在创建线程的时候,传一个可调用的类的实例来供线程启动的时候执行,这是一种更面为对象的方法。

    代码如下:

    import threading
    from time import sleep, ctime
    
    loops = [4, 2]
    
    class ThreadFunc(object):
        def __init__(self, func, args, name=''):
            self.name = name
            self.func = func
            self.args = args
    
        def __call__(self):
            self.res = self.func(*self.args)
    
    def loop(nloop, nsec):
        print 'start loop %s at: %s
    ' %(nloop, ctime()),
        sleep(nsec)
        print 'loop %s done at: %s
    ' %(nloop, ctime()),
    
    def main():
        print 'starting at:', ctime()
        threads = []
        nloops = range(len(loops))
    
        for i in nloops:
            t = threading.Thread(
                target = ThreadFunc(loop, (i,loops[i]),
                                    loop.__name__))
            threads.append(t)
    
        for i in nloops:
            threads[i].start()
    
        for i in nloops:
            threads[i].join()
    
        print 'all DONE at:', ctime()
    
    if __name__ == '__main__':
        main()

    结果和上面是一样的,这里就不贴了。

    可以看到我们怎家了一个ThreadFunc类和创建Thread对象时实例化一个可调用类ThreadFunc的类对象。

    创建线程时,Thread对象会调用我们的ThreadFunc对象,会用到一个特殊函数__call__(),由于我们已经有了要用的参数,所以不再传到Thread()构造器中。

    最后一种方法是从Thread类中派生一个子类,然后创造这个子类的实例。

    import threading
    from time import sleep, ctime
    
    loops = [2, 4]
    
    class MyThread(threading.Thread):
        def __init__(self, func, args, name=''):
            threading.Thread.__init__(self)
            self.name = name
            self.func = func
            self.args = args
    
        def run(self):
            apply(self.func, self.args)
    
    def loop(nloop, nsec):
        print 'start loop%s at: %s' %(nloop, ctime())
        sleep(nsec)
        print 'loop%s done at:%s' %(nloop, ctime())
    
    def main():
        print 'starting at:%s' % ctime()
        threads = []
        nloops = range(len(loops))
    
        for i in nloops:
            t = MyThread(loop, (i, loops[i]),
                          loop.__name__)
            threads.append(t)
    
        for i in nloops:
            threads[i].start()
    
        for i in nloops:
            threads[i].join()
    
        print 'all DONE at: %s' % ctime()
    
    if __name__ == '__main__':
        main()
            
  • 相关阅读:
    java继承
    Linux下word转pdf以及unoconv中文乱码问题
    jquery点击事件捕获
    在Windows上玩TensorFlow(一)——安装Docker【转】
    php面试总结
    [转载] PHP 线程,进程和并发
    微信小程序数据解密
    sql基础整理
    PHP 底层的运行机制与原理【转载】
    react-native 运行原理【转载】
  • 原文地址:https://www.cnblogs.com/SRL-Southern/p/5095958.html
Copyright © 2020-2023  润新知