python多线程之t.setDaemon(True) 和 t.join()

0.目录

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

1.参考

C:\Program Files\Anaconda2\Lib\threading.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),主线程结束后,守护子线程随之中止。

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

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

3.验证过程

(1)没有将子线程设置为守护进程,主线程结束后,各子线程继续运行。

#!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), 主线程结束后,守护子线程随之中止。

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
时间: 2024-10-04 19:48:31

python多线程之t.setDaemon(True) 和 t.join()的相关文章

Python多线程之threading Event

Python threading模块提供了Event对象用于线程间通信,它提供了设置.清除.等待等方法用于实现线程间的通信.event是最简单的进程间通信方式之一,一个线程产生一个信号,另一个线程则等待该信号.Python 通过threading.Event()产生一个event对象,event对象维护一个内部标志(标志初始值为False),通过set()将其置为True,wait(timeout)则用于阻塞线程直至Flag被set(或者超时,可选的),isSet()用于查询标志位是否为True

python多线程之Condition(条件变量)

#!/usr/bin/env python # -*- coding: utf-8 -*- from threading import Thread, Condition import time items = [] condition = Condition() class Consumer(Thread): def __init__(self): Thread.__init__(self) def consume(self): global condition global items co

Python多线程之threading模块

使用threading.Thread类,有三种创建线程的方法: 创建一个Thread类,传给它一个函数: 创建一个Thread类,传给它一个可调用的类对象: 从Thread派生出一个类,创建一个这个子类的实例. # 方法1和方法2的创建方法类似 import threading def func(k):     print('thread %s replies %s'%(threading.currentThread().getName(), k**2)) if __name__ == '__m

Python 多线程之threading condition

使用Condition对象可以在某些事件触发或者达到特定的条件后才处理数据,Condition除了具有Lock对象的acquire方法和release方法外,还有wait方法.notify方法.notifyAll方法等用于条件处理. threading.Condition([lock]):创建一个condition,支持从外界引用一个Lock对象(适用于多个condtion共用一个Lock的情况),默认是创建一个新的Lock对象. acquire()/release():获得/释放 Lock w

python多线程之threading、ThreadPoolExecutor.map

背景: 某个应用场景需要从数据库中取出几十万的数据时,需要对每个数据进行相应的操作.逐个数据处理过慢,于是考虑对数据进行分段线程处理: 方法一:使用threading模块 代码: 1 # -*- coding: utf-8 -*- 2 import math 3 import random 4 import time 5 from threading import Thread 6 7 _result_list = [] 8 9 10 def split_df(): 11 # 线程列表 12 t

python 线程之 threading(三)

python 线程之 threading(一)http://www.cnblogs.com/someoneHan/p/6204640.html python 线程之 threading(二)http://www.cnblogs.com/someoneHan/p/6209240.html 使用threading.Thread.is_alive()这个方法可以判断线程是否是存活状态.但是在现有的基础上不能够直到线程什么时候开始,什么时候结束,什么时候被打断. 如果有一个或者多个线程需要在另外的一个线

python 线程之 threading(四)

python 线程之 threading(三) http://www.cnblogs.com/someoneHan/p/6213100.html中对Event做了简单的介绍. 但是如果线程打算一遍一遍的重复通知某个事件.应该使用Condition 1. 使用Condition首先应该获取Condition即使Condition进入锁的状态 2. 在线程执行过程中需要等待其他线程通知,然后才开始向下运行的地方使用Condition.wait()方法,线程进入阻塞状态. 3. 使用Condition

多线程之Openstack novnc 改造,缓解Nova压力

#!/usr/bin/env python #-*-coding:UTF-8-*- """ @Item   :  Socket learing @Author :  William @Group  :  DEV Group @Date   :  2013-10-16 @Funtion: """ import sys,os,time,redis,traceback,json,threading,socket from cloud.hsnovnc i

Java多线程之DaemonThreadFactory

通过DaemonThreadFactory创建后台线程池 另外:如果是后台线程创建的线程,将都是后台线程. package wzh.daemon; import java.util.concurrent.ThreadFactory; public class DaemonThreadFactory implements ThreadFactory { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r);