多任务,简单来说就是操作系统可以同时运行多个任务,比如你一边用浏览器浏览着网页,一边使用音乐播放器听歌,还一边修改着word文档,除此之外,还有许多应用程序同时在后台运行着,只是桌面没有显示。
对于现在的电脑,多核CPU已比较常见了,即使之前的单核CPU也可以实现多任务,只不过单核CPU中操作系统让各个任务交替执行,事实上比如让任务一执行0.001秒,然后再让任务二执行0.001秒,接着任务三可能也执行0.001秒,由于CPU处理数据执行代码的速度很快,我们肉眼 看起来感觉所有的任务都在一起执行一样。
并发:指的是任务数多于CPU核心数,操作系统通过调度算法,实现将多个任务"一起执行"(事实上总有一些任务没有执行,只是看起来是一起执行而已)
并行:指的是任务数小于CPU核心数,即多个任务真正是同时执行的。
线程
单线程执行:
#coding=utf-8
import time
def sorry():
print("我错了,对不起...")
time.sleep(1)
if __name__ == "__main__":
for i in range(5):
sorry()
运行结果:
多线程执行:
需要使用threading模块
#coding=utf-8
import time
import threading
def sorry():
print("我错了,对不起...")
time.sleep(1)
if __name__ == "__main__":
for i in range(5):
t1=threading.Thread(target=sorry)
t1.start()#启动线程,让线程开始执行
运行结果:
可以明显的看到多线程并发的操作,花费的时间很短,当调用start()方法时,才会真正创建线程,开始执行。
主线程等待子线程执行完毕才结束:
#coding=utf-8
import time
import threading
def sorry():
print("我错了,对不起...")
time.sleep(1)
def OK():
print("OK,原谅你了...")
time.sleep(1)
if __name__ == "__main__":
print("-----开始------")
t1=threading.Thread(target=sorry)
t2=threading.Thread(target=OK)
t1.start()
t2.start()
time.sleep(5)#延时五秒,主线程会等待子线程全部执行完毕再结束
print("------结束-------")
输出结果:
查看线程数量:
#coding=utf-8
import time
import threading
def sing():
for i in range(5):
print("正在唱香水有毒%d..."%i)
time.sleep(1)
def dance():
for i in range(5):
print("正在跳芭蕾舞%d..."%i)
time.sleep(1)
if __name__ == "__main__":
print("-----开始-------")
t1=threading.Thread(target=sing)
t2=threading.Thread(target=dance)
t1.start()
t2.start()
while True:
length=len(threading.enumerate())#threading.enumerate()可以获取当前运行的线程数
print("当前运行的线程数为:%d"%length)
if length<=1:
break
time.sleep(1)
运行结果:主线程加上它创建的两个子线程,因此当前运行的线程数为3
线程执行代码的封装:通过上面的代码可以看出,通过threading模块可以实现多任务的执行,为了使每个线程的封装性更好,使 用threading模块时,往往定义一个新的子类class,只要继承threading.Thread,然后重写run()方法就可以了。
python的threading.Thread类有一个run方法,用于定义线程的功能函数,可以在自己的线程类中覆盖该方法。而创建自己的线程实例后,通过Thread类的start方法,可以启动该线程,交给python虚拟机进行调度,当该线程获得执行的机会时,就会调用run方法执行线程。
#coding=utf-8
import time
import threading
class MyThread(threading.Thread):
def run(self):
for i in range(3):
time.sleep(1)
msg="I'm" + self.name +"@"+ str(i)
print(msg)
def test():
for i in range(5):
t=MyThread()
t.start()
if __name__ == "__main__":
test()
运行结果:
从代码和执行结果我们可以看出,多线程程序的执行顺序是不确定的。当执行到sleep语句时,线程将被阻塞(Blocked),到sleep结束后,线程进入就绪(Runnable)状态,等待调度。而线程调度将自行选择一个线程执行。上面的代码中只能保证每个线程都运行完整个run函数,但是线程的启动顺序、run函数中每次循环的执行顺序都不能确定。
注意:
1.每个线程都默认有一个名字,尽管上述代码中name并未指定name,但python会自动为线程指定一个名字。
2.当线程的run方法结束时,该线程结束。
3.虽然无法控制线程调度程序,但可以通过别的方式影响线程调度的方式。