关于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\n"

程序输出:

I am thread1

I am thread2

ok

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

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

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

这个时候程序会输出:

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\n"

这时程序输出:

I am thread1

I am thread2

I am thread1

I am thread2

I am thread1

I am thread2

I am thread1

。。。

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

之前的实验中,两个子线程的运行时间是一样的,那么假如两个线程耗时不一样,一个子线程先于另一个子线程完成执行,会发生什么情况呢,于是我增加了一个什么都不干的方法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\n"

这段代码的执行结果是:

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, "\n"

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

关于python多线程编程中join()和setDaemon()的一点儿探究的更多相关文章

  1. python多线程编程

    Python多线程编程中常用方法: 1.join()方法:如果一个线程或者在函数执行的过程中调用另一个线程,并且希望待其完成操作后才能执行,那么在调用线程的时就可以使用被调线程的join方法join( ...

  2. 【C/C++开发】多线程编程中的join函数

    多线程编程中的join函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # coding: utf-8 # 测试多线程中join的 ...

  3. day-3 python多线程编程知识点汇总

    python语言以容易入门,适合应用开发,编程简洁,第三方库多等等诸多优点,并吸引广大编程爱好者.但是也存在一个被熟知的性能瓶颈:python解释器引入GIL锁以后,多CPU场景下,也不再是并行方式运 ...

  4. Java多线程编程(2)--多线程编程中的挑战

    一.串行.并发和并行   为了更清楚地解释这三个概念,我们来举一个例子.假设我们有A.B.C三项工作要做,那么我们有以下三种方式来完成这些工作:   第一种方式,先开始做工作A,完成之后再开始做工作B ...

  5. Java多线程编程中Future模式的详解

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...

  6. C++ 关于MFC多线程编程中的一些注意事项 及自定义消息的处理

    在多线程编程中,最简单的方法,无非就是利用 AfxBeginThread  来创建一个工作线程,看一下这个函数的说明: CWinThread* AFXAPI AfxBeginThread( AFX_T ...

  7. Java多线程编程中Future模式的详解<转>

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...

  8. Qt多线程编程中的对象线程与函数执行线程

    近来用Qt编写一段多线程的TcpSocket通信程序,被其中Qt中报的几个warning搞晕了,一会儿是说“Cannot create children for a parent that is in ...

  9. C#多线程编程中的锁系统

    C#多线程编程中的锁系统(二) 上章主要讲排他锁的直接使用方式.但实际当中全部都用锁又太浪费了,或者排他锁粒度太大了. 这一次我们说说升级锁和原子操作. 目录 1:volatile 2:  Inter ...

随机推荐

  1. iOS开发之 动画CoreAnimation

    http://blog.treney.com/index.php/archives/CoreAnimation.html?hmsr=toutiao.io&utm_medium=toutiao. ...

  2. vb.net向Excel中写入值

    根据网上例子结合自己的工具环境修改后测试可以通过 我使用的工具:Microsoft Visual Studio 2010,Excel 2007 一.在D盘新建一个temp文件夹用于存放Excel启动时 ...

  3. Java用筛子法求素数

    描述现在给出你一些数,要求你写出一个程序,输出这些整数相邻最近的素数,并输出其相距长度.如果左右有等距离长度素数,则输出左侧的值及相应距离.如果输入的整数本身就是素数,则输出该素数本身,距离输出0   ...

  4. jQuery Validate 插件[表单验证]

    在客户端添加信息提交表单时我们经常需要做一些验证,比如验证不能为空,验证客户输入手机格式,验证客户输入email,url等的格式,我们可以通过EL表达式结合js 进行自主验证,今天总结一个JQuery ...

  5. SpringMVC中使用Jcaptcha实现校验码验证

    SpringMVC中使用Jcaptcha实现校验码验证:http://www.tuicool.com/articles/rMzAFj 本文将使用Jcaptcha实现校验码验证,并演示在Spring/S ...

  6. ceph运维命令合集

    一.集群 1.启动一个ceph进程 启动mon进程 [root@ceph-adm ~]#203.109 service ceph start mon.ceph-mon1 启动msd进程 [root@c ...

  7. linux压缩解压缩

    一.tar • -c:创建新文档• -x:解压缩归档文件• -f 文件名:使用归档文件• -j:使用bzip2解压缩• -z:使用gzip解压缩• -v:详细输出模式 1.压缩命令: 命令格式:tar ...

  8. [设计模式]<<设计模式之禅>>关于里氏替换原则

    在面向对象的语言中,继承是必不可少的.非常优秀的语言机制,它有如下优点:● 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性:● 提高代码的重用性:● 子类可以形似父类,但又异于父类,“龙 ...

  9. hdu 2838 树状数组

    思路:从后面往前面插,用一个二维树状数组保存,c[i][0]表示比i小的元素和,c[i][1]表示比i小的元素个数. #include<iostream> #include<cstr ...

  10. poj 2186 强连通分支 和 spfa

    思路: 建图时,分别建正向图edge和转置图T.用正向图edge来DFS,找出第一个被发现的强连通分支(如果该图存在题目要求的点,那么一定就是第一个被发现的).然后用spfa跑转置图T,判断被发现的点 ...