VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • Python3标准库:threading进程中管理并发操作(3)

',
  • )
  •  
  • for i in range(3):
  • t = threading.Thread(target=worker, daemon=True)
  • t.start()
  •  
  • main_thread = threading.main_thread()
  • for t in threading.enumerate():
  • if t is main_thread:
  • continue
  • logging.debug('joining %s', t.getName())
  • t.join()
  • 由于工作线程睡眠的时间量是随机的,所以这个程序的输出可能有变化。

    1.5 派生线程

    开始时,Thread要完成一些基本初始化,然后调用其run()方法,这会调用传递到构造函数的目标函数。要创建Thread的一个子类,需要覆盖run()来完成所需的工作。

    
    	
    1. import threading
    2. import logging
    3.  
    4. class MyThread(threading.Thread):
    5.  
    6. def run(self):
    7. logging.debug('running')
    8.  
    9. logging.basicConfig(
    10. level=logging.DEBUG,
    11. format='(%(threadName)-10s) %(message)s',
    12. )
    13.  
    14. for i in range(5):
    15. t = MyThread()
    16. t.start()

    run()的返回值将被忽略。

    由于传递到Thread构造函数的args和kwargs值保存在私有变量中(这些变量名都有前缀),所以不能很容易地从子类访问这些值。要向一个定制的线程类型传递参数,需要重新定义构造函数,将这些值保存在子类可见的一个实例属性中。

    
    	
    1. import threading
    2. import logging
    3.  
    4. class MyThreadWithArgs(threading.Thread):
    5.  
    6. def __init__(self, group=None, target=None, name=None,
    7. args=(), kwargs=None, *, daemon=None):
    8. super().__init__(group=group, target=target, name=name,
    9. daemon=daemon)
    10. self.args = args
    11. self.kwargs = kwargs
    12.  
    13. def run(self):
    14. logging.debug('running with %s and %s',
    15. self.args, self.kwargs)
    16.  
    17. logging.basicConfig(
    18. level=logging.DEBUG,
    19. format='(%(threadName)-10s) %(message)s',
    20. )
    21.  
    22. for i in range(5):
    23. t = MyThreadWithArgs(args=(i,), kwargs={'a': 'A', 'b': 'B'})
    24. t.start()

    MyThreadwithArgs使用的API与Thread相同,不过类似于其他定制类,这个类可以轻松地修改构造函数方法,以取得更多参数或者与线程用途更直接相关的不同参数。

    1.6 定时器线程

    有时出于某种原因需要派生Thread,Timer就是这样一个例子,Timer也包含在threading中。Timer在一个延迟之后开始工作,而且可以在这个延迟期间内的任意时刻被取消。

    
    	
    1. import threading
    2. import time
    3. import logging
    4.  
    5. def delayed():
    6. logging.debug('worker running')
    7.  
    8. logging.basicConfig(
    9. level=logging.DEBUG,
    10. format='(%(threadName)-10s) %(message)s',
    11. )
    12.  
    13. t1 = threading.Timer(0.3, delayed)
    14. t1.setName('t1')
    15. t2 = threading.Timer(0.3, delayed)
    16. t2.setName('t2')
    17.  
    18. logging.debug('starting timers')
    19. t1.start()
    20. t2.start()
    21.  
    22. logging.debug('waiting before canceling %s', t2.getName())
    23. time.sleep(0.2)
    24. logging.debug('canceling %s', t2.getName())
    25. t2.cancel()
    26. logging.debug('done')

    这个例子中,第二个定时器永远不会运行,看起来第一个定时器在主程序的其余部分完成之后还会运行。由于这不是一个守护线程,所以在主线程完成时其会隐式退出。

    1.7 线程间传送信号

    尽管使用多线程的目的是并发地运行单独的操作,但有时也需要在两个或多个线程中同步操作。事件对象是实现线程间安全通信的一种简单方法。Event管理一个内部标志,调用者可以用set()和clear()方法控制这个标志。其他线程可以使用wait()暂停,直到这个标志被设置,可有效地阻塞进程直至允许这些线程继续。

    
    	
    
    相关教程