zoukankan      html  css  js  c++  java
  • 关于python多线程编程中join()和setDaemon()的一点儿探究

    关于python多线程编程中join()和setDaemon()的用法,这两天我看网上的资料看得头晕脑涨也没看懂,干脆就做一个实验来看看吧。

    首先是编写实验的基础代码,创建一个名为MyThread的 类,然后通过向这个类传入print_func这个方法,分别创建了两个子线程:

     

    #!/usr/bin/env python
    import
    threading
    import time


    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 print_func(num): while True: print "I am thread%d" % num time.sleep(1) threads = [] t1 = MyThread(print_func, (1, ), print_func.__name__) threads.append(t1) t2 = MyThread(print_func, (2, ), print_func.__name__) threads.append(t2)

     

    首先来试试setDaemon()的设置,在上面基础代码的后面加上以下的代码:

    for t in threads:
        t.setDaemon(True)
        t.start()
    
    print "ok
    "

    程序输出:

    I am thread1 

    I am thread2 

     ok

    print_func()中的while循环没有继续执行下去就退出了,可见由于setDaemon(True)把子线程设置为守护线程,子线程启动后,父线程也继续执行下去,当父线程执行完最后一条语句print "ok "后,没有等待子线程,直接就退出了,同时子线程也一同结束。

    下面我们把添加的代码更改如下:

    for t in threads:
        t.start()
        t.join()
    
    print "ok
    "

    这个时候程序会输出:

    I am thread1 

    I am thread1 

    I am thread1 

    I am thread1 

    I am thread1 

    I am thread1 

    I am thread1

    。。。

    这样一直循环下去,可见只有第一个子线程被调用了,第二个子线程,以及父线程都没有继续走下去。这里我的理解是:join()的作用是,在子线程完成运行之前,这个子线程的父线程将一直被阻塞。,无法运行下去。在这里父线程没法继续执行for循环,所以第二个子线程也就不会出现了。

    接下来再修改一下代码:

    for t in threads:
        t.start()
    
    for t in threads:
        t.join()
    
    print "ok
    "

    这时程序输出:

    I am thread1 

    I am thread2 

    I am thread1 

    I am thread2 

    I am thread1 

    I am thread2 

    I am thread1 

    。。。

    可见这个时候两个子线程都在运行了,同样在两个子线程完成之前,父线程的print "ok "都不会执行。

     

    之前的实验中,两个子线程的运行时间是一样的,那么假如两个线程耗时不一样,一个子线程先于另一个子线程完成执行,会发生什么情况呢,于是我增加了一个什么都不干的方法pass_func:

    #! /usr/bin/env python
    #coding=utf-8
    import threading
    import time
    
    
    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 print_func(num):
    
        while True:
            print "I am thread%d" % num
            time.sleep(1)
    
    
    def pass_func():
        pass
    
    threads = []
    t1 = MyThread(print_func, (1, ), print_func.__name__)
    threads.append(t1)
    t2 = MyThread(pass_func, (), pass_func.__name__)
    threads.append(t2)
    
    for t in threads:
        t.start()
    
    for t in threads:
        t.join()
    
    print "ok
    "

     

    这段代码的执行结果是:

    I am thread1 

    I am thread1 

    I am thread1 

    I am thread1 

    I am thread1 

    I am thread1 

    I am thread1 

    I am thread1 

    。。。

    可见这时侯,一个子线程的完成不会影响另外一个子线程,父线程仍然一直被阻塞着。

    有些时候,还可以单独对某一个子线程设定join(),以达到特定的效果,例如下面这段代码片段的用意是,分别设立一个子线程用于接收数据,另外一个子线程用于发送数据,当用户输入“quit”时,程序退出:

    def send(sck):
        while True:
            data = raw_input('>')
            sck.send(data)
            if  data == "quit":
                sck.close()
                break
    
    def recieve(sck):
        while True:
            data = sck.recv(BUFSIZ)
            print data, "
    "
    
    threads
    = [] t1 = threading.Thread(target=send, args = (tcpCliSock, )) threads.append(t1) t2 = threading.Thread(target=recieve, args = (tcpCliSock, )) threads.append(t2) for t in threads: t.start() t1.join()

    这段代码中,把t1,也就是send所对应的子线程添加上join()属性,让父线程在send方法对应的子线程结束前一直在阻塞状态。假如把两个子线程t1t2都添加上join()属性,这会使得send方法收到“quit”命令,退出循环后,由于recieve方法仍然在循环当中,父线程仍然被阻塞着,结果程序无法退出。只对t1添加join()属性,那么t1结束了,父线程会继续执行下去,直到执行完最后一条代码后退出,然后t2也跟着一同结束,达到所有线程都退出的目的,这就是t1.join()这条命令的用意。

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 交换Easy
    Java实现 蓝桥杯VIP 算法提高 多项式输出
    Java实现 蓝桥杯VIP 算法提高 多项式输出
    Java实现 蓝桥杯VIP 算法提高 多项式输出
    Java实现 蓝桥杯VIP 算法提高 多项式输出
    Java实现 蓝桥杯VIP 算法提高 多项式输出
    Java实现 蓝桥杯VIP 算法训练 矩阵乘方
    QT中给各控件增加背景图片(可缩放可旋转)的几种方法
    回调函数实现类似QT中信号机制
    std::string的Copy-on-Write:不如想象中美好(VC不使用这种方式,而使用对小字符串更友好的SSO实现)
  • 原文地址:https://www.cnblogs.com/cjyfff/p/3662355.html
Copyright © 2011-2022 走看看