Python 多线程 VS 多进程(一)

网友投稿 465 2022-05-29

多线程 vs 多进程

程序:一堆代码以文本形式存入一个文档

进程:程序运行的一个状态

包含地址空间、内容、数据栈等

每个进程由自己完全独立的运行环境,多进程共享数据是一个问题

线程

一个进程的独立运行片段,一个进程可以有多个线程

轻量化的进程

一个进程的多个线程间共享数据和上下文运行环境

共享互斥问题

全局解释器锁(GTL)

python 代码的执行是由python 虚拟机进行控制

在主循环中只能有一个控制线程在执行

python 包

thread:有问题,不好用,python3改成了_thread

threading:通行的包

案例01: 顺序执行,耗时比较长

''' 利用time函数,生成两个函数 程序调试 计算总的运行时间 ''' import time def loop1(): # ctime 得到当前时间 print("Start loop 1 at : ",time.ctime()) time.sleep(4) print("End loop 1 at : ", time.ctime()) def loop2(): # ctime 得到当前时间 print("Start loop 2 at : ", time.ctime()) # 睡眠多长时间,单位是秒 time.sleep(2) print("End loop 2 at : ", time.ctime()) def main(): print("Starting at : ", time.ctime()) loop1() loop2() print("All done at : ", time.ctime()) if __name__ == '__main__': main()

Starting at : Tue Aug 13 19:10:31 2019 Start loop 1 at : Tue Aug 13 19:10:31 2019 End loop 1 at : Tue Aug 13 19:10:35 2019 Start loop 2 at : Tue Aug 13 19:10:35 2019 End loop 2 at : Tue Aug 13 19:10:37 2019 All done at : Tue Aug 13 19:10:37 2019

案例02:改用多线程,缩短总时间,使用_thread

''' 利用time函数,生成两个函数 程序调试 计算总的运行时间 ''' import time import _thread as thread def loop1(): # ctime 得到当前时间 print("Start loop 1 at : ",time.ctime()) time.sleep(4) print("End loop 1 at : ", time.ctime()) def loop2(): # ctime 得到当前时间 print("Start loop 2 at : ", time.ctime()) # 睡眠多长时间,单位是秒 time.sleep(2) print("End loop 2 at : ", time.ctime()) def main(): print("Starting at : ", time.ctime()) # 启动多线程的意思是用多线程去执行某个函数 # 启动多线程函数为start_new_thread # 参数两个,一个是需要运行的函数名,第二个是函数的参数作为元组使用,为空则使用空元组 # 注意,如果函数只有一个参数,需要参数后有一个逗号 thread.start_new_thread(loop1, ()) thread.start_new_thread(loop2, ()) print("All done at : ", time.ctime()) if __name__ == '__main__': main() while True: time.sleep(1)

Starting at : Tue Aug 13 19:14:47 2019 All done at : Tue Aug 13 19:14:47 2019 Start loop 1 at : Tue Aug 13 19:14:47 2019 Start loop 2 at : Tue Aug 13 19:14:47 2019 End loop 2 at : Tue Aug 13 19:14:49 2019 End loop 1 at : Tue Aug 13 19:14:51 2019

案例03:多线程,传参数

# 利用time延时函数,生成两个函数 # 利用多线程调用 # 计算总运行时间 # 练习带参数的多线程启动方法 import time # 导入多线程包并更名为thread import _thread as thread def loop1(in1): # ctime 得到当前时间 print('Start loop 1 at: ', time.ctime()) # 把参数打印出来 print("我是参数", in1) # 睡眠多长时间,单位是秒 time.sleep(4) print('End loop 1 at: ', time.ctime()) def loop2(in1, in2): # ctime 得到当前时间 print('Start loop 2 at: ', time.ctime()) # 把参数in1 和 in2 打印出来,代表使用 print("我是参数", in1, "和参数", in2) # 睡眠多长时间,单位是秒 time.sleep(4) print('End loop 2 at: ', time.ctime()) def main(): print("Starting at : ", time.ctime()) # 启动多线程的意思是用多线程去执行某个函数 # 启动多线程函数为start_new_thread # 参数两个,一个是需要运行的函数名,第二个是函数的参数作为元组使用,为空则使用空元组 # 注意,如果函数只有一个参数,需要参数后有一个逗号 thread.start_new_thread(loop1, ("王老大", )) thread.start_new_thread(loop2, ("王大鹏", "王晓鹏")) print("All done at : ", time.ctime()) if __name__ == '__main__': main() # 一定要有while语句 # 因为启动多线程后本程序就作为主线程存在 # 如果主线程执行完毕,则子线程可能也需要终止 while True: time.sleep(10)

Starting at : Tue Aug 13 19:17:10 2019 All done at : Tue Aug 13 19:17:10 2019 Start loop 1 at: Tue Aug 13 19:17:10 2019 我是参数 王老大 Start loop 2 at: Tue Aug 13 19:17:10 2019 我是参数 王大鹏 和参数 王晓鹏 End loop 1 at: Tue Aug 13 19:17:14 2019 End loop 2 at: Tue Aug 13 19:17:14 2019

threading的使用

直接利用threading.Thread生成Thread实例

t = threading.Thread(target=xxx, args=(xxx, ))

t.start(): 启动多线程

t.join(): 等待多线程执行完成

案例04

# 利用time延时函数,生成两个函数 # 利用多线程调用 # 计算总运行时间 # 练习带参数的多线程启动方法 import time # 导入多线程包并更名为thread import threading def loop1(in1): # ctime 得到当前时间 print('Start loop 1 at: ', time.ctime()) # 把参数打印出来 print("我是参数", in1) # 睡眠多长时间,单位是秒 time.sleep(4) print('End loop 1 at: ', time.ctime()) def loop2(in1, in2): # ctime 得到当前时间 print('Start loop 2 at: ', time.ctime()) # 把参数in1 和 in2 打印出来,代表使用 print("我是参数", in1, "和参数 ", in2) # 睡眠多长时间,单位是秒 time.sleep(2) print('End loop 2 at: ', time.ctime()) def main(): print("Starting at: ", time.ctime()) # 生成threading.Thread实例 t1 = threading.Thread(target=loop1, args=("王老大",)) t1.start() t2 = threading.Thread(target=loop2, args=("王大鹏", "王小鹏")) t2.start() print("All done at: ", time.ctime()) if __name__ == '__main__': main() # 一定要有while语句 # 因为启动多线程后本程序就作为主线程存在 # 如果主线程执行完毕,则子线程可能也需要终止 while True: time.sleep(10)

Starting at: Tue Aug 13 19:19:42 2019 Start loop 1 at: Tue Aug 13 19:19:42 2019 我是参数 王老大 Start loop 2 at: All done at: Tue Aug 13 19:19:42 2019 Tue Aug 13 19:19:42 2019 我是参数 王大鹏 和参数 王小鹏 End loop 2 at: Tue Aug 13 19:19:44 2019 End loop 1 at: Tue Aug 13 19:19:46 2019

案例05:加入join后比较案例04的结果的异同

# 利用time延时函数,生成两个函数 # 利用多线程调用 # 计算总运行时间 # 练习带参数的多线程启动方法 import time # 导入多线程包并更名为thread import threading def loop1(in1): # ctime 得到当前时间 print('Start loop 1 at: ', time.ctime()) # 把参数打印出来 print("我是参数", in1) # 睡眠多长时间,单位是秒 time.sleep(4) print('End loop 1 at: ', time.ctime()) def loop2(in1, in2): # ctime 得到当前时间 print('Start loop 2 at: ', time.ctime()) # 把参数in1 和 in2 打印出来,代表使用 print("我是参数", in1, "和参数 ", in2) # 睡眠多长时间,单位是秒 time.sleep(2) print('End loop 2 at: ', time.ctime()) def main(): print("Starting at: ", time.ctime()) # 生成threading.Thread实例 t1 = threading.Thread(target=loop1, args=("王老大",)) t1.start() t2 = threading.Thread(target=loop2, args=("王大鹏", "王小鹏")) t2.start() t1.join() t2.join() print("All done at: ", time.ctime()) if __name__ == '__main__': main() # 一定要有while语句 # 因为启动多线程后本程序就作为主线程存在 # 如果主线程执行完毕,则子线程可能也需要终止 while True: time.sleep(10)

Starting at: Tue Aug 13 19:21:58 2019 Start loop 1 at: Tue Aug 13 19:21:58 2019 我是参数 王老大 Start loop 2 at: Tue Aug 13 19:21:58 2019 我是参数 王大鹏 和参数 王小鹏 End loop 2 at: Tue Aug 13 19:22:00 2019 End loop 1 at: Tue Aug 13 19:22:02 2019 All done at: Tue Aug 13 19:22:02 2019

守护线程-daemon

如果在程序中将子线程设置成守护线程,则子线程会在主线程结束的时候自动退出

一般认为,守护线程不重要或者不允许离开主线程独立运行

守护线程案例能否有效果跟环境相关

案例06非守护线程

import time import threading def fun(): print("Start fun") time.sleep(2) print("end fun") print("Main thread") t1 = threading.Thread(target=fun, args=() ) t1.start() time.sleep(1) print("Main thread end")

Main thread Start fun Main thread end end fun

案例07守护线程

import time import threading def fun(): print("Start fun") time.sleep(2) print("end fun") print("Main thread") t1 = threading.Thread(target=fun, args=() ) # 启动之前设置 t1.setDaemon(True) # t1.daemon = True t1.start() time.sleep(1) print("Main thread end")

Main thread Start fun Main thread end

线程常用属性

threading.currentThread:返回当前线程变量

threading.enumerate:返回一个包含正在运行的线程的list,正在运行的线程指的是线程启动后,结束前的状态

threading.activeCount: 返回正在运行的线程数量,效果跟 len(threading.enumerate)相同

thr.setName: 给线程设置名字

thr.getName: 得到线程的名字

Python 多线程 VS 多进程(一)

案例08

import time import threading def loop1(): # ctime 得到当前时间 print("Start loop 1 at : ",time.ctime()) time.sleep(6) print("End loop 1 at : ", time.ctime()) def loop2(): # ctime 得到当前时间 print("Start loop 2 at : ",time.ctime()) time.sleep(1) print("End loop 2 at : ", time.ctime()) def loop3(): # ctime 得到当前时间 print("Start loop 3 at : ",time.ctime()) time.sleep(5) print("End loop 3 at : ", time.ctime()) def main(): print("Starting at: ", time.ctime()) # 生成threading.Thread实例 t1 = threading.Thread(target=loop1, args=( )) # setName是给每一个子线程设置一个名字 t1.setName("THR_1") t1.start() t2 = threading.Thread(target=loop2, args=( )) t2.setName("THR_2") t2.start() t3 = threading.Thread(target=loop3, args=( )) t3.setName("THR_3") t3.start() # 预期3秒后,thread2已经结束 time.sleep(3) # enumerate 得到正在运行子线程,即子线程1和子线程3 for thr in threading.enumerate(): # getName能够得到线程的名字 print("正在运行的线程名字是: {0}".format(thr.getName())) print("正在运行的子线程数量为: {0}".format(threading.activeCount())) print("All done at: ", time.ctime()) if __name__ == '__main__': main() # 一定要有while语句 # 因为启动多线程后本程序就作为主线程存在 # 如果主线程执行完毕,则子线程可能也需要终止 while True: time.sleep(10)

Starting at: Tue Aug 13 19:28:20 2019 Start loop 1 at : Tue Aug 13 19:28:20 2019 Start loop 2 at : Tue Aug 13 19:28:20 2019 Start loop 3 at : Tue Aug 13 19:28:20 2019 End loop 2 at : Tue Aug 13 19:28:21 2019 正在运行的线程名字是: MainThread 正在运行的线程名字是: THR_1 正在运行的线程名字是: THR_3 正在运行的子线程数量为: 3 All done at: Tue Aug 13 19:28:23 2019 End loop 3 at : Tue Aug 13 19:28:25 2019 End loop 1 at : Tue Aug 13 19:28:26 2019

直接继承自threading.Thread

直接继承Thread

重写run函数

类实例可以直接运行

案例09

import threading import time # 1. 类需要继承来自threading.Thread class MyThread(threading.Thread): def __init__(self, arg): super().__init__() self.arg = arg # 2. 必须重写run函数,run函数代表的是真正执行的功能 def run(self): time.sleep(2) print("The args for this class is {0}".format(self.arg)) for i in range(5): t = MyThread(i) t.start() t.join() print("Main thread is done!!!!!!!!")

The args for this class is 0 The args for this class is 1 The args for this class is 2 The args for this class is 3 The args for this class is 4 Main thread is done!!!!!!!!

案例10 工业风案例

import threading from time import sleep, ctime loop = [4, 2] class ThreadFunc: def __init__(self, name): self.name = name def loop(self, nloop, nsec): ''' :param nloop:loop函数的名称 :param nsec:系统休眠时间 :return: ''' print('Start loop', nloop, 'at ', ctime()) sleep(nsec) print('Done loop', nloop, 'at ', ctime()) def main(): print("Starting at: ", ctime()) # ThreadFunc("loop").loop 跟以下两个式子相等 # t = ThreadFunc("loop") # t.loop # 以下t1 和 t2的定义方式相等 t = ThreadFunc("loop") t1 = threading.Thread( target=t.loop, args=("LOOP1", 4)) # 下面这种写法更西方人,工业化一点 t2 = threading.Thread( target=ThreadFunc('loop').loop, args=('LOOP2', 2)) # 常见错误写法 # t1 = threading.Thread(target=ThreadFunc('loop').loop(100,4)) # t2 = threading.Thread(target=ThreadFunc('loop').loop(100,2)) t1.start() t2.start() t1.join() t2.join() print("All done at: ", ctime()) if __name__ == '__main__': main() # 一定要有while语句 # 因为启动多线程后本程序就作为主线程存在 # 如果主线程执行完毕,则子线程可能也需要终止 while True: sleep(10)

Starting at: Tue Aug 13 19:31:16 2019 Start loop LOOP1 at Tue Aug 13 19:31:16 2019 Start loop LOOP2 at Tue Aug 13 19:31:16 2019 Done loop LOOP2 at Tue Aug 13 19:31:18 2019 Done loop LOOP1 at Tue Aug 13 19:31:20 2019 All done at: Tue Aug 13 19:31:20 2019

Python 任务调度 多线程

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:漫谈“数据湖”之价值与架构
下一篇:诡异的并发之可见性
相关文章