python3的多线程很多人无法理解是怎么运行的,因此本文从程序猿的日常生活出发,写了一个由浅入深的多线程教程,这样子大家就不会觉得陌生了,多线程真的很简单很简单!

不要讲多线程局限于库或者框架,自己造轮子才是最大的快乐。

-----------------------------------------以下是正文--------------------------------------------

假设我是一个程序猿,我想听歌,但是我又要打码,所以有:

我听完歌就去打码:

  1. #!/usr/bin/python3.4
  2. # -*- coding: utf-8 -*-
  3.  
  4. import time
  5.  
  6. def matter1(music):
  7. print("我想听这些歌")
  8.  
  9. for i in range(0,len(music)):
  10. print("第" + str(i + 1) + "首歌是:" + str(music[i]))
  11. # 当前时间为
  12. print(time.strftime('%Y%H%M%S', time.localtime()))
  13. # 假设每一首歌曲的时间是2秒
  14. time.sleep(2)
  15. print("切换下一首歌...")
  16.  
  17. def matter2(number):
  18. print("我在打码")
  19.  
  20. j = 0
  21. while j <= number:
  22. print("我准备写入第" + str(j + 1) +"行代码")
  23. j = j + 1
  24. # 当前时间为
  25. print(time.strftime('%Y%H%M%S', time.localtime()))
  26. # 假设每写一行代码的时间为1秒
  27. time.sleep(1)
  28. print("写下一行代码...")
  29.  
  30. if __name__ == '__main__':
  31.  
  32. start = time.time()
  33.  
  34. # 设定我要听的歌为
  35. music = ["music1","music2","music3"]
  36. # 开始听歌
  37. matter1(music)
  38. # 设定我要打码的行数
  39. number = 5
  40. # 开始打码
  41. matter2(number)
  42.  
  43. end = time.time()
  44. print("完成的时间为:" + str(end - start))

记录来的完成时间为:

  1. 完成的时间为:12.007483959197998

时间上完全符合,但是身为一个程序猿,可以一边打码一边听歌,那么设计一个多线程,让他们同时进行:

  1. #!/usr/bin/python3.4
  2. # -*- coding: utf-8 -*-
  3.  
  4. import time
  5. import threading
  6.  
  7. def matter1(music):
  8. print("我想听这些歌")
  9.  
  10. for i in range(0,len(music)):
  11. print("第" + str(i + 1) + "首歌是:" + str(music[i]))
  12. # 当前时间为
  13. print(time.strftime('%Y%H%M%S', time.localtime()))
  14. # 假设每一首歌曲的时间是2秒
  15. time.sleep(2)
  16. print("切换下一首歌...")
  17.  
  18. def matter2(number):
  19. print("我在打码")
  20.  
  21. j = 0
  22. while j <= number:
  23. print("我准备写入第" + str(j + 1) +"行代码")
  24. j = j + 1
  25. # 当前时间为
  26. print(time.strftime('%Y%H%M%S', time.localtime()))
  27. # 假设每写一行代码的时间为1秒
  28. time.sleep(1)
  29. print("写下一行代码...")
  30.  
  31. if __name__ == '__main__':
  32. # 设定我要听的歌为
  33. music = ["music1","music2","music3"]
  34.  
  35. # 设定我要打码的行数
  36. number = 5
  37. # 建立一个新数组
  38. threads = []
  39. # 将听歌放入数组里面
  40. thing1 = threading.Thread(target=matter1, args=(music,))
  41. threads.append(thing1)
  42. # 将打码放入数组里面
  43. thing2 = threading.Thread(target=matter2, args=(number,))
  44. threads.append(thing2)
  45.  
  46. # 开始时间
  47. start = time.time()
  48. # 写个for让两件事情都进行
  49. for thing in threads:
  50. # setDaemon为主线程启动了线程matter1和matter2
  51. # 启动也就是相当于执行了这个for循环
  52. thing.setDaemon(True)
  53. thing.start()
  54.  
  55. # 结束时间
  56. end = time.time()
  57. print("完成的时间为:" + str(end - start))

但是直接就结束了?

  1. 完成的时间为:0.0010008811950683594

原来是setDaemon,主线程启动两个子线程后做事后,主线程就不管子线程是否运行完毕,直接往下运行,直接运行到

  1. print("完成的时间为:" + str(end - start))

然后程序就结束了,因此,为了防止子线程还没结束主线程就结束的意外情况,在程序里面加个join:

  1. import time
  2. import threading
  3.  
  4. def matter1(music):
  5. print("我想听这些歌")
  6.  
  7. for i in range(0,len(music)):
  8. print("第" + str(i + 1) + "首歌是:" + str(music[i]))
  9. # 当前时间为
  10. print(time.strftime('%Y%H%M%S', time.localtime()))
  11. # 假设每一首歌曲的时间是2秒
  12. time.sleep(2)
  13. print("切换下一首歌...")
  14.  
  15. def matter2(number):
  16. print("我在打码")
  17.  
  18. j = 0
  19. while j <= number:
  20. print("我准备写入第" + str(j + 1) +"行代码")
  21. j = j + 1
  22. # 当前时间为
  23. print(time.strftime('%Y%H%M%S', time.localtime()))
  24. # 假设每写一行代码的时间为1秒
  25. time.sleep(1)
  26. print("写下一行代码...")
  27.  
  28. if __name__ == '__main__':
  29. # 设定我要听的歌为
  30. music = ["music1","music2","music3"]
  31.  
  32. # 设定我要打码的行数
  33. number = 5
  34. # 建立一个新数组
  35. threads = []
  36. # 将听歌放入数组里面
  37. thing1 = threading.Thread(target=matter1, args=(music,))
  38. threads.append(thing1)
  39. # 将打码放入数组里面
  40. thing2 = threading.Thread(target=matter2, args=(number,))
  41. threads.append(thing2)
  42.  
  43. # 开始时间
  44. start = time.time()
  45. # 写个for让两件事情都进行
  46. for thing in threads:
  47. # setDaemon为主线程启动了线程matter1和matter2
  48. # 启动也就是相当于执行了这个for循环
  49. thing.setDaemon(True)
  50. thing.start()
  51.  
  52. # 子线程没结束前主线程会被卡在这里
  53. thing1.join()
  54. thing2.join()
  55. # 结束时间
  56. end = time.time()
  57. print("完成的时间为:" + str(end - start))

最后运行的时间就是打码的时间:

  1. 完成的时间为:6.003339052200317

这就真正做到了一边听歌一边打码的双手互博的状态,本文后面的那0.003333秒就别纠结了,系统运行程序花个0.0033333秒不过分吧

偷懒打码打4行:

  1. number = 4
  2. 完成的时间为:5.008083820343018

------------------------------我是快乐的分割线------------------------------

网上的多线程都是写成“类”的形式,这里写成函数不符合“大众”标准,那么就改成类的形式:

  1. #!/usr/bin/python3.4
  2. # -*- coding: utf-8 -*-
  3.  
  4. import time
  5. import threading
  6.  
  7. class MyThread(threading.Thread):
  8. def __init__(self, func, args, name=''):
  9. threading.Thread.__init__(self)
  10. self.name = name
  11. self.func = func
  12. self.args = args
  13. #self.counter = counter
  14.  
  15. def run(self):
  16. # 某某线程要开始了
  17. print(self.name + "开始了##################")
  18.  
  19. if self.name == "听歌线程":
  20. matter1(music)
  21. elif self.name == "打码线程":
  22. matter2(number)
  23. print(self.name + "结束了##################")
  24.  
  25. def matter1(music):
  26. for i in range(0,len(music)):
  27. print("第" + str(i + 1) + "首歌是:" + str(music[i]))
  28. # 假设每一首歌曲的时间是2秒
  29. time.sleep(2)
  30. print("切换下一首歌...")
  31.  
  32. def matter2(number):
  33. j = 0
  34. while j <= number:
  35. print("我准备写入第" + str(j + 1) +"行代码")
  36. j = j + 1
  37. # 假设每写一行代码的时间为1秒
  38. time.sleep(1)
  39. print("写下一行代码...")
  40.  
  41. if __name__ == '__main__':
  42. # 设定我要听的歌为
  43. music = ["music1","music2","music3"]
  44.  
  45. # 设定我要打码的行数
  46. number = 4
  47.  
  48. # 开始时间
  49. start = time.time()
  50.  
  51. thing1 = MyThread(matter1, music,"听歌线程")
  52. thing2 = MyThread(matter2, number, "打码线程")
  53. thing1.start()
  54. thing2.start()
  55. thing1.join()
  56. thing2.join()
  57.  
  58. # 结束时间
  59. end = time.time()
  60. print("完成的时间为:" + str(end - start))

运行结果也是6秒:

  1. 完成的时间为:6.001942157745361

----------------------我是快乐的分割线-------------------------

程序猿在跑代码的时候是很无聊的,无聊的时候就会想到去吃零食,那么我就加入一个函数:

  1. #!/usr/bin/python3.4
  2. # -*- coding: utf-8 -*-
  3.  
  4. import time
  5. import threading
  6.  
  7. class MyThread(threading.Thread):
  8. def __init__(self, func, args, name=''):
  9. threading.Thread.__init__(self)
  10. self.name = name
  11. self.func = func
  12. self.args = args
  13. #self.counter = counter
  14.  
  15. def run(self):
  16. # 某某线程要开始了
  17. print(self.name + "开始了##################")
  18.  
  19. if self.name == "听歌线程":
  20. matter1(music)
  21. elif self.name == "打码线程":
  22. matter2(number)
  23. elif self.name == "零食线程":
  24. matter3(snacks)
  25. print(self.name + "结束了##################")
  26.  
  27. def matter1(music):
  28. for i in range(0,len(music)):
  29. print("第" + str(i + 1) + "首歌是:" + str(music[i]))
  30. # 假设每一首歌曲的时间是2秒
  31. time.sleep(2)
  32. print("切换下一首歌...")
  33.  
  34. def matter2(number):
  35. j = 0
  36. while j <= number:
  37. print("我准备写入第" + str(j + 1) +"行代码")
  38. j = j + 1
  39. # 假设每写一行代码的时间为1秒
  40. time.sleep(1)
  41. print("写下一行代码...")
  42.  
  43. def matter3(snacks):
  44. for k in range(0,len(snacks)):
  45. print("我正在听着歌吃" + str(snacks[k]) + "零食")
  46. #每吃一袋零食间隔5秒
  47. time.sleep(5)
  48. print("吃完了一包零食")
  49.  
  50. if __name__ == '__main__':
  51. # 设定我要听的歌为
  52. music = ["music1","music2","music3"]
  53.  
  54. # 设定我要打码的行数
  55. number = 4
  56.  
  57. # 设定我想吃的零食
  58. snacks = ["咪咪","辣条"]
  59.  
  60. # 开始时间
  61. start = time.time()
  62.  
  63. thing1 = MyThread(matter1, music,"听歌线程")
  64. thing2 = MyThread(matter2, number, "打码线程")
  65. thing3 = MyThread(matter3, snacks, "零食线程")
  66. thing1.start()
  67. thing2.start()
  68. thing3.start()
  69. thing1.join()
  70. thing2.join()
  71. thing3.join()
  72.  
  73. # 结束时间
  74. end = time.time()
  75. print("完成的时间为:" + str(end - start))

程序运行的时间是:

  1. 完成的时间为:10.000968933105469

感觉还是吃零食比较耗时间。但是但是,程序猿只有两个手,那么吃零食和打码是不能同时进行了,那么这里加个线程锁:

  1. #!/usr/bin/python3.4
  2. # -*- coding: utf-8 -*-
  3.  
  4. import time
  5. import threading
  6.  
  7. # 打开线程锁
  8. lock = threading.Lock()
  9.  
  10. class MyThread(threading.Thread):
  11. def __init__(self, func, args, name=''):
  12. threading.Thread.__init__(self)
  13. self.name = name
  14. self.func = func
  15. self.args = args
  16. #self.counter = counter
  17.  
  18. def run(self):
  19. # 某某线程要开始了
  20. print(self.name + "开始了##################")
  21.  
  22. if self.name == "听歌线程":
  23. matter1(music)
  24. elif self.name == "打码线程":
  25. matter2(number)
  26. elif self.name == "零食线程":
  27. matter3(snacks)
  28. print(self.name + "结束了##################")
  29.  
  30. def matter1(music):
  31. for i in range(0,len(music)):
  32. print("第" + str(i + 1) + "首歌是:" + str(music[i]))
  33. # 假设每一首歌曲的时间是2秒
  34. time.sleep(2)
  35. print("切换下一首歌...")
  36.  
  37. def matter2(number):
  38. lock.acquire()
  39. j = 0
  40. while j <= number:
  41. print("我准备写入第" + str(j + 1) +"行代码")
  42. j = j + 1
  43. # 假设每写一行代码的时间为1秒
  44. time.sleep(1)
  45. print("写下一行代码...")
  46. lock.release()
  47.  
  48. def matter3(snacks):
  49. lock.acquire()
  50. for k in range(0,len(snacks)):
  51. print("我正在听着歌吃" + str(snacks[k]) + "零食")
  52. #每吃一袋零食间隔5秒
  53. time.sleep(5)
  54. print("吃完了一包零食")
  55. lock.release()
  56.  
  57. if __name__ == '__main__':
  58. # 设定我要听的歌为
  59. music = ["music1","music2","music3"]
  60.  
  61. # 设定我要打码的行数
  62. number = 4
  63.  
  64. # 设定我想吃的零食
  65. snacks = ["咪咪","辣条"]
  66.  
  67. # 开始时间
  68. start = time.time()
  69.  
  70. thing1 = MyThread(matter1, music,"听歌线程")
  71. thing2 = MyThread(matter2, number, "打码线程")
  72. thing3 = MyThread(matter3, snacks, "零食线程")
  73. thing1.start()
  74. thing2.start()
  75. thing3.start()
  76. thing1.join()
  77. thing2.join()
  78. thing3.join()
  79.  
  80. # 结束时间
  81. end = time.time()
  82. print("完成的时间为:" + str(end - start))

运行时间为:

  1. 完成的时间为:15.001857995986938

这里解释一下:

  1. 只是听歌和打码花的时间是5s多;
  2.  
  3. 听歌、打码、吃零食同时进行是10s多;

加了线程锁后,打码和吃零食不能同时进行,那么就变成:

  1. 听歌和打码花的时间是5s多;
  2.  
  3. 单独吃零食是10s多,加起来就是15秒;

为了验证吃零食的时候还是听着歌的,所以将听歌的时间间隔改成10s,得到的运行时间为:

  1. 完成的时间为:30.000711917877197

运行结果贴出来看一下:

  1. 听歌线程开始了##################
  2. 1首歌是:music1
  3. 打码线程开始了##################
  4. 我准备写入第1行代码
  5. 零食线程开始了##################
  6. 写下一行代码...
  7. 我准备写入第2行代码
  8. 写下一行代码...
  9. 我准备写入第3行代码
  10. 写下一行代码...
  11. 我准备写入第4行代码
  12. 写下一行代码...
  13. 我准备写入第5行代码
  14. 写下一行代码...
  15. 打码线程结束了##################
  16. 我正在听着歌吃咪咪零食
  17. 切换下一首歌...
  18. 2首歌是:music2
  19. 吃完了一包零食
  20. 我正在听着歌吃辣条零食
  21. 吃完了一包零食
  22. 零食线程结束了##################
  23. 切换下一首歌...
  24. 3首歌是:music3
  25. 切换下一首歌...
  26. 听歌线程结束了##################

perfect!

python3多线程趣味详解的更多相关文章

  1. python3多线程应用详解(第四卷:图解多线程中LOCK)

    先来看下图形对比: 发现没有这种密集型计算的任务中,多线程没有穿行的速率快,原因就是多线程在线程切换间也是要耗时的而密集型计算任务执行时几乎没以偶IO阻塞,这样你说谁快

  2. python3多线程应用详解(第二卷:多线程到底是怎么工作的)

    现在很多人都说用多线程工作快是因为多个不同任务可以同时执行,注意我说的是不同任务,要是重复做一件事达到相同效果就是画蛇添足了,其实这是个错误的说法,线程真正的本质是无法同时执行的.现在我们来看下多线程 ...

  3. python3多线程应用详解(第三卷:图解多线程中join,守护线程应用)

  4. python3多线程应用详解(第一卷:线程的本质概念)

    之前我用过多线程的方式执行了爬虫程序,爬取了糗事百科的数据可以看到速率非常之快,就像正常一个人他要完一个汉堡,再吃喝一瓶水才能走,结果他边吃汉堡边喝水,速率一下加快了一样.首先我们看看什么是线程: 图 ...

  5. .NET多线程同步方法详解

    .NET多线程同步方法详解(一):自由锁(InterLocked) .NET多线程同步方法详解(二):互斥锁(lock) NET多线程同步方法详解(三):读写锁(ReadWriteLock) .NET ...

  6. Mac OS X10.9安装的Python2.7升级Python3.4步骤详解

    Mac OS X10.9安装的Python2.7升级Python3.4步骤详解 Mac OS X10.9默认带了Python2.7,不过现在Python3.4.0出来了,如果想使用最新版本,赶紧升级下 ...

  7. Java多线程——多线程方法详解

    本系列文章是Java多线程的详解介绍,对多线程还不熟悉的同学可以先去看一下我的这篇博客Java基础系列3:多线程超详细总结,这篇博客从宏观层面介绍了多线程的整体概况,接下来的几篇文章是对多线程的深入剖 ...

  8. Swift - 多线程GCD详解

    //  GCD详解 //  目录: //  1. 创建GCD队列(最常用) //  2. 自定义创建队列 //  3. 使用多线程实现延迟加载 //  4. 使用多线程实现重复(循环) //  5. ...

  9. python3 常用模块详解

    这里是python3的一些常用模块的用法详解,大家可以在这里找到它们. Python3 循环语句 python中模块sys与os的一些常用方法 Python3字符串 详解 Python3之时间模块详述 ...

随机推荐

  1. AmazeUI基本样式

    AmazeUI是一个轻量级.Mobile first的前端框架,基于开源社区流行的前端框架编写. Normalize AmazeUI使用了normalize.css,但做了些调整:html添加了-we ...

  2. UI基础:UIActionSheet和UIAlterView

    iOS中有两个弹出视图的控件,分别是UIActionSheet和UIAlterView.效果图如下:       主要代码如下: - (void)viewDidLoad { [super viewDi ...

  3. Editplus 正则表达式 删除含有指定字符串的行 删除注释

    1.删除含有指定字符串的行 替换:  ^.*(指定字符串).*$  为空 例如,删除含有"JOIN"的行, 替换:  ^.*JOIN.*$   为空 2.删除//行注释 替换: / ...

  4. LCA(Tarjan)

    program LCA(Tarjan); type arr=record u,v,w,next:longint; end; ; maxm=; ..maxm*] of arr; last,lasq,an ...

  5. alt text 与 tooltip区别

    在做工具的Accessiblity测试时, 对于image对象,一直分不清它的alt属性与tooltip属性的区别与用法, 从网上查了下, 比较认同这样的观点: alt属性: alternative ...

  6. Qt Clipboard剪贴板简单使用

    设置剪贴板的内容 QClipboard *clipboard = QApplication::clipboard(); clipboard->setText("contents&quo ...

  7. Aborting commit: 'XXXXXXXX'remains in conflict错误

    今天在提交项目文件到本地SVN时提示错误如下: 过期:”global.php“在事务”21-1“, You have to update your working copy first. 运行upda ...

  8. CSS 实现:checkbox

    <div class="wrap"> <label>性别:</label> <div class="cb-wrap"& ...

  9. CentOS安装时小坑记录

    在安装CentOS的时候,由于第一次安装小白,将VM虚拟机的内存设置为512M,导致进行安装的时候无法进入正常的画面安装模式,只能使用简版安装界面,可能对于很多小白不是很熟悉,特此记录,安装CentO ...

  10. C/C++中的隐藏依赖

    转载自:http://trarck.googlecode.com/svn/trunk/article/C/%E9%9A%90%E8%97%8F%E4%BE%9D%E8%B5%96.txt 隐藏依赖:即 ...