多任务的概念
什么叫“多任务”呢?简单地说,就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。
现在,多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?
答案就是操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。
真正的并行执行多任务只能在多核CPU上实现,但是,由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。
注意:
并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)
并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的
线程基础python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用
单线程执行 import time def test(): print("test...") time.sleep(1) if __name__ == '__main__': for i in range(5): test()执行效果:程序在控制台每隔一秒打印test...
多线程执行 import time import threading def test(): print("test...") time.sleep(1) if __name__ == '__main__': for i in range(5): t = threading.Thread(target=test) t.start() # 启动线程执行效果:程序在控制台一下子输出五行test...,等待1秒左右结束
说明:
可以明显看出使用了多线程并发的操作,花费时间要短很多
当调用start()时,才会真正的创建线程,并且开始执行
主线程会等待所有子线程结束后才结束 import time import threading def playPhone(): print('玩手机...') time.sleep(1) def eat(): print("吃东西...") time.sleep(1) if __name__ == '__main__': print("--开始--") t1 = threading.Thread(target=playPhone) t1.start() t2 = threading.Thread(target=eat) t2.start() print('--执行结束')执行效果:主线程阻塞1秒左右后程序结束,说明主线程在等待其他线程执行完毕。
查看线程数量 print('玩手机...') time.sleep(1) def eat(): for i in range(10): print("吃东西...") time.sleep(1) if __name__ == '__main__': print("--开始--") t1 = threading.Thread(target=playPhone) t1.start() t2 = threading.Thread(target=eat) t2.start() # 查看正在执行的线程数量 while True: length = len(threading.enumerate()) print("当前运行的线程数量:%d" % length) print("这些线程是:%s" % str(threading.enumerate())) if length == 1: break time.sleep(0.5) print('--执行结束')在python中,调用threading.enumerate()能获取当前正在运行的所有线程,返回值是一个list,调用length()函数并传入该list对象就获取到当前运行线程的数量。
线程-注意点 线程执行代码的封装通过上一篇,能够看出,通过使用threading模块能完成多任务的程序开发,为了让每个线程的封装性更完美,所以使用threading模块时,往往会定义一个新的子类class,只要继承threading.Thread就可以了,然后重写run方法。
示例如下:
import time import threading class MyThread(threading.Thread): def run(self): for i in range(5): time.sleep(1) print("我是%s@%d" % (self.name, i)) if __name__ == "__main__": mt = MyThread() mt.start()运行结果如下:
我是Thread-1@0 我是Thread-1@1 我是Thread-1@2 我是Thread-1@3 我是Thread-1@4python的threading.Thread类有一个run方法,用于定义线程的功能函数,可以在自己的线程类中覆盖该方法。而创建自己的线程实例后,通过Thread类的start方法,可以启动该线程,交给python虚拟机进行调度,当该线程获得执行的机会时,就会调用run方法执行线程。
线程的执行顺序 mport time import threading class MyThread(threading.Thread): def run(self): for i in range(5): time.sleep(1) print("我是%s@%d" % (self.name, i)) if __name__ == "__main__": for i in range(5): mt = MyThread() mt.start()执行结果(运行的结果可能不一样,但是大体是一致的):
我是Thread-5@0 我是Thread-2@0 我是Thread-3@0 我是Thread-4@0 我是Thread-1@0 我是Thread-3@1 我是Thread-4@1 我是Thread-2@1 我是Thread-5@1 我是Thread-1@1 我是Thread-3@2 我是Thread-4@2 我是Thread-2@2 我是Thread-5@2 我是Thread-1@2 我是Thread-3@3 我是Thread-4@3 我是Thread-2@3 我是Thread-5@3 我是Thread-1@3 我是Thread-3@4 我是Thread-4@4 我是Thread-5@4 我是Thread-2@4 我是Thread-1@4