多任务
多任务介绍
- 同时做多件事就是多任务,重点就是同时进行。
多任务理解
- 这里提出两个概念,并发和并行。
- 并发:CPU数量小于当前执行的多任务,假的多任务,并不是同一时刻才运行所有任务,而是通过时间片轮转的方式,高速的切换运行的任务达到短时间内运行多个任务的结果。
- 并行:CPU数量大于当前执行的多任务,真的多任务,因为CPU数量足够,所以每个任务由不同的CPU执行,实现了同时进行。
实现多任务方式
- 实现多任务有三种方式:
- 线程
- 进程
- 协程
线程
线程介绍
- 线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。
使用线程完成多任务
import threading # 内置模块
import time
def demo():
for i in range(3):
print("hello world")
time.sleep(1)
if __name__ == '__main__':
t = threading.Thread(target=demo)
t.start()
print("1")
- 主线程会等到子线程结束之后才会结束
- 从这个运行结果中也可以看出上面的结论,在第一次循环的时候,print语句已经执行,表示主线程已经执行完毕,但程序并没有结束,而是等到子线程的5次循环全部完成之后,才结束。
- 如果不想等待子线程结束后才结束,可以加入守护线程,如下:
import threading
import time
def main():
for i in range(5):
print('helloworld')
time.sleep(1)
if __name__ == '__main__':
t = threading.Thread(target=main,daemon=True)
t.start()
print('1')
- 加入守护线程即选择Thread的参数daemon为True,也可以写t.daemon(True)。daemon译为守护线程,加入了守护线程后,运行的结果为:
- 可以看出主线程并没有等待子线程的循环结束,再运行了print语句之后直接结束,子线程后面的循环也就看不到了。
- 除了守护线程之外,还有一个join方法,可以让主线程等待子线程执行完毕之后再执行,代码如下:
import threading
import time
def main():
for i in range(5):
print('helloworld')
time.sleep(1)
if __name__ == '__main__':
t = threading.Thread(target=main)
t.start()
t.join()
print('1')
- 运行结果如下:
- 不同于前两次的运行结果,加入了join之后,主线程会等待子线程运行结束,也就是子线程的循环完全结束,才会继续往下执行,而不是像第一个例子那样,先执行完主线程但不结束等待子线程运行完成,这里的顺序有一些不同。
查看线程数量
- 可以通过threading模块里面的enumerate来查看线程的数量
import threading
import time
def demo1():
for i in range(3):
print(f"--demo1--{i}")
time.sleep(1)
def demo2():
for i in range(3):
print(f"--demo2--{i}")
time.sleep(1)
def main():
t1 = threading.Thread(target=demo1)
t2 = threading.Thread(target=demo2)
t1.start()
t2.start()
print(threading.enumerate())
if __name__ == '__main__':
main()
验证子线程的执行和创建
- 当调用Thread的时候,不会创建线程。
- 当调用Thread创建出来的实例对象的start方法的时候,才会创建线程以及开始运行这个线程。
- 这里通过上面的查看线程数量的代码来查看子线程创建的过程
import threading
import time
def demo1():
for i in range(3):
print(f"--demo1--{i}")
time.sleep(1)
def demo2():
for i in range(3):
print(f"--demo2--{i}")
time.sleep(1)
def main():
print('创建前:',threading.enumerate())
t1 = threading.Thread(target=demo1)
t2 = threading.Thread(target=demo2)
print('创建后:',threading.enumerate())
t1.start()
t2.start()
print('运行后:',threading.enumerate())
if __name__ == '__main__':
main()
- 代码的执行结果如下:
- 通过结果我们也可以印证上面的结论,即子线程是在运行之后才创建出来的。
继承Thread类创建线程
import threading
import time
class A(threading.Thread):
def __init__(self,name):
super().__init__(name=name)
def run(self):
for i in range(5):
print(i)
if __name__ == "__main__":
t = A('test_name')
t.start()