zoukankan      html  css  js  c++  java
  • python多线程之t.setDaemon(True) 和 t.join()

    0.目录

    1.参考
    2.结论
        (1)通过 t.setDaemon(True) 将子线程设置为守护进程(默认False),主线程代码执行完毕后,python程序退出,无需理会守护子线程的状态。
        (2) t.join() 用于阻塞主线程,可以想象成将某个子线程的执行过程插入(join)到主线程的时间线上,主线程的后续代码延后执行。注意和 t.start() 分开写在两个for循环中。
        (3)第一个for循环同时启动了所有子线程,随后在第二个for循环中执行t.join() ,主线程实际被阻塞的总时长==其中执行时间最长的一个子线程。
    3.验证过程

    1.参考

    C:Program FilesAnaconda2Lib hreading.py

        def daemon(self):
            """A boolean value indicating whether this thread is a daemon thread (True) or not (False).
    
            This must be set before start() is called, otherwise RuntimeError is
            raised. Its initial value is inherited from the creating thread; the
            main thread is not a daemon thread and therefore all threads created in
            the main thread default to daemon = False.
    
            The entire Python program exits when no alive non-daemon threads are
            left.
    
            """
        def join(self, timeout=None):
            """Wait until the thread terminates.
    
            This blocks the calling thread until the thread whose join() method is
            called terminates -- either normally or through an unhandled exception
            or until the optional timeout occurs.
    
            When the timeout argument is present and not None, it should be a
            floating point number specifying a timeout for the operation in seconds
            (or fractions thereof). As join() always returns None, you must call
            isAlive() after join() to decide whether a timeout happened -- if the
            thread is still alive, the join() call timed out.
    
            When the timeout argument is not present or None, the operation will
            block until the thread terminates.
    
            A thread can be join()ed many times.
    
            join() raises a RuntimeError if an attempt is made to join the current
            thread as that would cause a deadlock. It is also an error to join() a
            thread before it has been started and attempts to do so raises the same
            exception.
    
            """

    2.结论

    (1)通过 t.setDaemon(True) 将子线程设置为守护进程(默认False),主线程代码执行完毕后,python程序退出,无需理会守护子线程的状态。

    (2) t.join() 用于阻塞主线程,可以想象成将某个子线程的执行过程插入(join)到主线程的时间线上,主线程的后续代码延后执行。注意和 t.start() 分开写在两个for循环中。

    (3)第一个for循环同时启动了所有子线程,随后在第二个for循环中执行t.join() ,主线程实际被阻塞的总时长==其中执行时间最长的一个子线程。

    3.验证过程

    (1)子线程默认为【非守护线程】,主线程代码执行完毕,各子线程继续运行,直到所有【非守护线程】结束,python程序退出。

    #!usr/bin/env python
    #coding:utf-8
    import time
    import random
    import logging
    
    import thread
    import threading
    from Queue import Queue
    
    lock = threading.Lock()     #'function-call ownership'
    rlock = threading.RLock()   #thread ownership
    
    def get_logger():
        logger = logging.getLogger("threading_example")
        logger.setLevel(logging.DEBUG)
        
        # fh = logging.FileHandler("d:/threading.log")
        fh = logging.StreamHandler()
        fmt = '%(asctime)s - %(threadName)-10s - %(levelname)s - %(message)s'
        formatter = logging.Formatter(fmt)
        fh.setFormatter(formatter)
    
        logger.addHandler(fh)
        return logger
    logger = get_logger()
    #################################
    
    class MyThread(threading.Thread):
        def __init__(self, number):
            threading.Thread.__init__(self)  
            self.number = number
        def run(self):
            for i in range(2):
                logger.debug(i)
                time.sleep(self.number)
     
    def main():
        logger.debug('MainThread Start')
        threads = [MyThread(3-i) for i in range(3)]  
        
        for t in threads:
            t.start()
    
        logger.debug('MainThread End')
     
     
    if __name__ == '__main__':
        main()

    输出:

    2017-08-15 17:04:12,512 - MainThread - DEBUG - MainThread Start
    2017-08-15 17:04:12,512 - Thread-1   - DEBUG - 0
    2017-08-15 17:04:12,513 - Thread-2   - DEBUG - 0
    2017-08-15 17:04:12,513 - Thread-3   - DEBUG - 0
    2017-08-15 17:04:12,513 - MainThread - DEBUG - MainThread End
    2017-08-15 17:04:13,513 - Thread-3   - DEBUG - 1
    2017-08-15 17:04:14,513 - Thread-2   - DEBUG - 1
    2017-08-15 17:04:15,513 - Thread-1   - DEBUG - 1

    (2) t.setDaemon(True), 主线程代码执行完毕,直接退出python程序,无需理会【守护】子线程的状态。

    def main():
        logger.debug('MainThread Start')
        threads = [MyThread(3-i) for i in range(3)]  
        
        for t in threads:
            t.setDaemon(True)   #将子线程设置为守护进程    
            t.start()
    
        logger.debug('MainThread End')

    输出:

    2017-08-15 17:06:20,822 - MainThread - DEBUG - MainThread Start
    2017-08-15 17:06:20,822 - Thread-1   - DEBUG - 0
    2017-08-15 17:06:20,823 - Thread-2   - DEBUG - 0
    2017-08-15 17:06:20,823 - MainThread - DEBUG - MainThread End
    2017-08-15 17:06:20,823 - Thread-3   - DEBUG - 0

    (3)错误用法: d t1.join()阻塞了主线程的for循环,t1结束后才执行t2.start()...实际就变成了单线程顺序执行。

    def main():
        logger.debug('MainThread Start')
        threads = [MyThread(3-i) for i in range(3)]  
        
        for t in threads:
            t.start()
            t.join()
            logger.debug('{} start() join() activeCount: {}'.format(t.getName(), threading.activeCount()))
    
        logger.debug('MainThread End')

    输出:

    2017-08-15 17:17:38,219 - MainThread - DEBUG - MainThread Start
    2017-08-15 17:17:38,230 - Thread-1   - DEBUG - 0
    2017-08-15 17:17:41,230 - Thread-1   - DEBUG - 1
    2017-08-15 17:17:44,232 - MainThread - DEBUG - Thread-1 start() join() activeCount: 1
    2017-08-15 17:17:44,232 - Thread-2   - DEBUG - 0
    2017-08-15 17:17:46,232 - Thread-2   - DEBUG - 1
    2017-08-15 17:17:48,233 - MainThread - DEBUG - Thread-2 start() join() activeCount: 1
    2017-08-15 17:17:48,233 - Thread-3   - DEBUG - 0
    2017-08-15 17:17:49,234 - Thread-3   - DEBUG - 1
    2017-08-15 17:17:50,234 - MainThread - DEBUG - Thread-3 start() join() activeCount: 1
    2017-08-15 17:17:50,234 - MainThread - DEBUG - MainThread End

    (4)异常用法:只对for循环的最后一个子线程执行了t.join() ,如果该子线程的执行时长不是所有子线程中最久的,可能达不到预期效果。

    def main():
        logger.debug('MainThread Start')
    # threads = [MyThread(3-i) for i in range(3)] threads
    = [MyThread((3-i)*2) for i in range(3)] #修改了等待时间 for t in threads: t.start() logger.debug('MainThread ing') # for t in threads: t.join() logger.debug('{} is_alive: {} join() activeCount: {}'.format(t.getName(), t.is_alive(), threading.activeCount())) logger.debug('MainThread End')

    输出:

    2017-08-15 18:18:10,924 - MainThread - DEBUG - MainThread Start
    2017-08-15 18:18:10,927 - Thread-1   - DEBUG - 0
    2017-08-15 18:18:10,930 - Thread-2   - DEBUG - 0
    2017-08-15 18:18:10,931 - Thread-3   - DEBUG - 0
    2017-08-15 18:18:10,931 - MainThread - DEBUG - MainThread ing
    2017-08-15 18:18:12,931 - Thread-3   - DEBUG - 1
    2017-08-15 18:18:14,931 - Thread-2   - DEBUG - 1
    2017-08-15 18:18:14,931 - MainThread - DEBUG - Thread-3 is_alive: False join() activeCount: 3
    2017-08-15 18:18:14,931 - MainThread - DEBUG - MainThread End
    2017-08-15 18:18:16,928 - Thread-1   - DEBUG - 1

    (5)正常用法:第二个for循环保证每一个子线程都执行了t.join(), 虽然t1运行结束后才执行t2.join(), 但是第一个for循环已经启动了所有子线程,所以主线程实际被阻塞的总时长==其中执行时间最长的一个子线程。

    def main():
        logger.debug('MainThread Start')
        # threads = [MyThread(3-i) for i in range(3)] 
        threads = [MyThread((i+1)*2) for i in range(3)]     #修改了等待时间
        
        for t in threads:
            t.start()
    
        logger.debug('MainThread ing')
        for t in threads:
            logger.debug('{} is_alive: {} join() activeCount: {}'.format(t.getName(), t.is_alive(), threading.activeCount()))
            t.join()        
        logger.debug('MainThread End')

    输出:

    2017-08-15 17:30:00,499 - MainThread - DEBUG - MainThread Start
    2017-08-15 17:30:00,499 - Thread-1   - DEBUG - 0
    2017-08-15 17:30:00,500 - Thread-2   - DEBUG - 0
    2017-08-15 17:30:00,500 - Thread-3   - DEBUG - 0
    2017-08-15 17:30:00,500 - MainThread - DEBUG - MainThread ing
    2017-08-15 17:30:00,500 - MainThread - DEBUG - Thread-1 is_alive: True join() activeCount: 4
    2017-08-15 17:30:02,500 - Thread-1   - DEBUG - 1
    2017-08-15 17:30:04,500 - Thread-2   - DEBUG - 1
    2017-08-15 17:30:04,500 - MainThread - DEBUG - Thread-2 is_alive: True join() activeCount: 3
    2017-08-15 17:30:06,500 - Thread-3   - DEBUG - 1
    2017-08-15 17:30:08,503 - MainThread - DEBUG - Thread-3 is_alive: True join() activeCount: 2
    2017-08-15 17:30:12,500 - MainThread - DEBUG - MainThread End
  • 相关阅读:
    BZOJ 4010: [HNOI2015]菜肴制作( 贪心 )
    bzoj 1084
    bzoj 2763
    bzoj 1003
    bzoj 1858
    codevs 1296
    cf 438D
    vijos 1083
    codevs 3303
    bzoj 1296
  • 原文地址:https://www.cnblogs.com/my8100/p/7366567.html
Copyright © 2011-2022 走看看