zoukankan      html  css  js  c++  java
  • python3多线程趣味详解

    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))

    记录来的完成时间为:

    完成的时间为: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))

    但是直接就结束了?

    完成的时间为:0.0010008811950683594
    

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

    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))

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

    完成的时间为:6.003339052200317
    

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

    偷懒打码打4行:

    number = 4
    完成的时间为: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 
    42 if __name__ == '__main__':
    43     # 设定我要听的歌为
    44     music = ["music1","music2","music3"]
    45 
    46     # 设定我要打码的行数
    47     number = 4
    48 
    49     # 开始时间
    50     start = time.time()
    51 
    52     thing1 = MyThread(matter1, music,"听歌线程")
    53     thing2 = MyThread(matter2, number, "打码线程")
    54     thing1.start()
    55     thing2.start()
    56     thing1.join()
    57     thing2.join()
    58 
    59     # 结束时间
    60     end = time.time()
    61     print("完成的时间为:" + str(end - start))

    运行结果也是6秒:

    完成的时间为: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))

    程序运行的时间是:

    完成的时间为: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))

    运行时间为:

    完成的时间为:15.001857995986938
    

    这里解释一下:

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

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

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

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

    完成的时间为: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!

  • 相关阅读:
    信息收集之DNS域名解析
    集合遍历利器 -- 迭代器模式 介绍 使用场景案例 优缺点及程序演示
    简单工厂的霸霸 -- 抽象工厂模式 介绍 使用场景案例 优缺点及程序演示
    可能是目前最易理解的手写promise
    chrome 开发者工具实用技巧
    gulp常用插件之modernizr使用
    koa-cors 跨域设置中间件
    在nodejs 中如何fs文件系统模块
    nodejs操作MongoDB数据库 MongoDB增、删、改、查
    vue动态渲染样式 class
  • 原文地址:https://www.cnblogs.com/TTyb/p/5846745.html
Copyright © 2011-2022 走看看