python的多线程简单实例理解

来源:互联网 发布:火焰之地怎么去乎门人 编辑:程序博客网 时间:2024/05/20 17:26

一直以来对于线程的理解是比较模糊的,之前在用php的时候,由于php是不直接支持多线程,要用php_threads的扩展。最近由于公司项目的后台需要要到多线程,故学习了一下python的多线程,下面通过一个简单的例子说明一下。

在实际中,比如说要听音乐,看电影,做其他的任务,按照单例的话,只能是一件做接着一件做。如果每件事都是很耗时的,那就会影响效率。同理在编程的世界里。同样有很多的相似的逻辑业务。比如群发邮件,按照单例我们的程序就会用循环的方式,发完一个再发一个。但是,发邮件的这个过程却是要耗时的,这样样子的浪费多长的时间才能将大量的邮件发完。而且程序还有一个超时时间限制呢!(虽然可以设置为无限制)。可想而知,这样子的话,就会造成效率低,甚至发送不成功。

下面进入主题

1、看一个简单的例子

#!D:\Python43\python.exe# -*- coding: UTF-8 -*-from time import ctime,sleep#听音乐def music(musicname):for i in range(2) :print("我正在听音乐叫%s,时间是:%s" %(musicname,ctime()))sleep(5)#看电影def movie(moviename):for j in range(2) :print("我正在看电影叫%s,时间是:%s" %(moviename,ctime()))sleep(2)#主线程if __name__ =='__main__':music('当爱已成往事')movie('中华英雄')print('所有的娱乐结束,时间:%s' %ctime())



定义两个函数,分别做两个任务,听音乐和看电影

music函数就是任务打印出听音乐这句话(程序执行非常快,纳秒级),这个时间是在15:36:56.然后等待5s,再去打印出听音乐这句话,时间是15:37:01,然后再睡眠等待5s.所以在这个过程任务的用时为10s.

接着到执行movie函数,睡眠时间2s.这个过程用时就是4s


最后,执行主程序的结束。我的娱乐任务完成。所以在这个过程他是按照程序单线程一直执行的。效率非常低。


2、多线程引入(非阻塞)

</pre><pre name="code" class="html">def music(musicname):for i in range(2) :print("我正在听音乐叫%s,时间是:%s" %(musicname,ctime()))sleep(2)#看电影def movie(moviename):for j in range(2) :print("我正在看电影叫%s,时间是:%s" %(moviename,ctime()))sleep(2)threads=[]t1 = threading.Thread(target=music,args=(u'一路顺风',))threads.append(t1)t2 = threading.Thread(target=movie,args=(u'让子弹飞',))threads.append(t2)#主线程if __name__ =='__main__':#循环执行子线程for t in threads :#将父线程设置为了守护线程。#根据setDaemon()方法的含义,#父线程打印内容后便结束了,#不管子线程是否执行完毕了。t.setDaemon(True)t.start()print('所有的娱乐结束,时间:%s' %ctime())



可以看到,在执行主程序的时候,三个任务基本是同时完成,而且music和movie只执行一遍,任务还没全部完成。为什么呢?

首先过程是先把所有的子线程启动,即musi和movie,这里是两条不同路,接着同时执行主程序的

print('所有的娱乐结束,时间:%s'%ctime()),又是一条路

主程序结束,就会将退出,同时子线程也退出,不管你的任务有没有完成。所以music和movie在启动并打印出那句话时,在睡眠等待,那边的主程序也已经执行到打印操作,所以主程序就退出,同时也通知正在睡眠等待的子线程退出。所以他们只执行一次打印任务,就被迫退出。为什么会被迫退出呢?那与我们的逻辑业务不符合啊。不急,接着往下看。原因就在于这个setDaemon(True)就是将主进程设置为守护线程,根据setDaemon()方法的含义,父线程打印内容后便结束了,不管子线程是否执行完毕了,都退出


3、多线程(阻塞)

#!D:\Python43\python.exe# -*- coding: UTF-8 -*-from time import ctime,sleepimport threading#听音乐def music(musicname):for i in range(2) :print("我正在听音乐叫%s,时间是:%s" %(musicname,ctime()))sleep(5)#看电影def movie(moviename):for j in range(2) :print("我正在看电影叫%s,时间是:%s" %(moviename,ctime()))sleep(2)threads=[]t1 = threading.Thread(target=music,args=(u'一路顺风',))threads.append(t1)t2 = threading.Thread(target=movie,args=(u'让子弹飞',))threads.append(t2)#主线程if __name__ =='__main__':#循环执行子线程for t in threads :#将父线程设置为了守护线程。#根据setDaemon()方法的含义,#父线程打印内容后便结束了,#不管子线程是否执行完毕了。<span style="color:#ff0000;">#t.setDaemon(True)</span>t.start()<span style="color:#ff0000;">for t in threads :t.join()</span>print('所有的娱乐结束,时间:%s' %ctime())



t.setDaemon(True)</span>
屏蔽掉,同时再加入一个for循环
for t in threads :<span style="white-space:pre"></span>t.join()

在执行主程序时,启动两个子线程,在15:18:09 同时执行一遍打印任务,两个子线程在睡眠等待中,时间到了,有同时个字执行一片打印任务。再睡眠等待2s后,再执行主程序的打印任务。

其实起作用的就是这个join()函数,这是一个阻塞函数,要子线程执行完了才能继续往下执行主程序(或其他程序)。

所以在for循环中,join()阻塞先等待第一个子线程结束后,在继续等待第二个子线程结束,如果第二个或者后面提前比前面的结束,则就会下一个join(),不需要等待(因为join()检查到该线程已经结束)。循环之后,就会往下执行主程序。所以整个过程所用的时间就是用时最长的任务的时间。所有的几乎是同时进行。

所以我们可以知道,setDaemon是与join()相对的。功能上基本是相反的

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 电器实体店生意越来越差怎么办 开业第一天不吉利怎么办 美容店开业第一天没人怎么办 淘宝店铺没有人访问怎么办 淘宝店铺没有人问怎么办 淘宝申请退款后店铺关闭怎么办 宝贝详情怎么改不了怎么办 改详情页后被删除宝贝怎么办 淘宝网商贷生意不好还不了怎么办 英国遗失在酒店物品怎么办 班福法则首位是0怎么办 同事能力比你强怎么办 新买的木板床响怎么办 笔记本键盘驱动坏了怎么办 云柜快递超时了怎么办 毕业设计被老师发现抄的怎么办 地板颜色太深了怎么办 皮质鞋子破皮了怎么办 吃了蜘蛛丝会怎么办 南京高二分班不公平怎么办? 高中分班考试没考好怎么办 实木门上的伸缩缝太深怎么办 mac点关机没反应怎么办 被压倒扁的易拉罐怎么办 白色车漏底漆了怎么办 客厅对着卧室门怎么办 老公不上进还懒怎么办 二胡按弦手指分不开怎么办 酷塑做完后疼痛怎么办 冷冻治疗后水泡破了怎么办 冷冻治疗的水泡破了怎么办? 冷冻治疗水泡破了怎么办 脚上冷冻后起泡怎么办 刺猴冷冻后起泡怎么办 隔壁太吵怎么办阴招 楼上有小孩太吵怎么办 捷达小水管睹了怎么办 楼房下水管冻了怎么办 一楼地面很潮湿怎么办 新房子地面有裂缝怎么办 地砖下面的下水管漏水怎么办