0 多任务
- 多任务:
- 一个系统可以同时运行多个程序,则该操作系统为多任务操作系统。(Windows、mac、Android)
- 一个程序可以同事执行多个任务,则该应用程序为多任务应用程序。
- 默认情况下,CPU的一个核运行一个程序,但实际上会运行多个,假装多任务。
- 并发:假的多任务。(一个CPU执行多个程序)
- 并行:真的多任务。(每个CPU执行单个程序)
- 实现多任务的两种方式:多线程、多进程;
1 threading(线程)
1.1 多线程
# 导入threading模块import threadingimport timedef say_hello():print('hello, Peter')time.sleep(1)if __name__ == '__main__':for i in range(5):# 创建对象t = threading.Thread(target=say_hello) # target参数为对某函数做标记,参数中的函数名不包括()# 创建线程t.start()
import threadingimport timedef task_1():for i in range(20):print('task_1 print: %s' % i)time.sleep(1)def task_2():for i in range(20):print('task_2 print: %s' % i)time.sleep(1)if __name__ == '__main__':t1 = threading.Thread(target=task_1)t2 = threading.Thread(target=task_2)t1.start()t2.start()for i in range(20):print('task_main print: %s' % i)time.sleep(1)# 该模块中,18-20执行的是主线程的打印任务,task_1和task_2微模块中的两个子线程;# 各线程执行的顺序不确定:执行代码时当前的运行环境可能不同、资源的分配可能不同,导致惨做系统调用顺序不一定一致;# task_1()或task_2()函数执行结束时,意味着其对应的线程结束;# 程序开始执行,就会有主线程调用。所有子线线程都结束主线程才会真正结束,即便18-20没有完成;
1.2 线程传参
import threadingimport timedef say_hello1(a):for i in range(10):print('hello', a)time.sleep(0.5)def say_hello2(a1, a2):for i in range(10):print(a1, 'says that hello', a2)time.sleep(0.5)def main():# ------------- <方法一> ------------- #b = threading.Thread(target=say_hello1, args=('Peter',))# args的参数为元组,单元素后要加,b.start()# ------------- <方法二> ------------- #c = threading.Thread(target=say_hello2, kwargs={'a1': 'Peter', 'a2': 'Joey'})# kwargs的参数为字典,key为字符串要带''c.start()if __name__ == '__main__':main()
1.3 线程信息
import threadingimport timedef thread_job():print('\nT1 start\n')for i in range(10): # 执行 0-9time.sleep(0.1)# print(i)print('\nT1 finish\n')def get_knowledge_of_thread():print('当前运行进程数量:%s' % threading.active_count()) # 当时同时进行几个进程print('当前运行的所有进程:%s' % threading.enumerate()) # 返回一个列表,包括所有当前进行的进程print('正在运行的线程:%s' % threading.current_thread()) # 返回正在运行的线程def main():get_knowledge_of_thread()added_thread = threading.Thread(target=thread_job, name='T1') # target的参数为函数名,且不带有()added_thread.start() # 开始线程get_knowledge_of_thread()added_thread.join() # 结束线程get_knowledge_of_thread() # 可看做所有线程成都运行结束才进行的任务if __name__ == '__main__':main()
C:\Users\ASUS\AppData\Local\Programs\Python\Python38-32\python.exe C:/Users/ASUS/PycharmProjects/pythonProject/test_20220511.py当前运行进程数量:1当前运行的所有进程:[<_MainThread(MainThread, started 10628)>]正在运行的线程:<_MainThread(MainThread, started 10628)>T1 start当前运行进程数量:2当前运行的所有进程:[<_MainThread(MainThread, started 10628)>, <Thread(T1, started 6040)>]正在运行的线程:<_MainThread(MainThread, started 10628)>0123456789T1 finish当前运行进程数量:1当前运行的所有进程:[<_MainThread(MainThread, started 10628)>]正在运行的线程:<_MainThread(MainThread, started 10628)>进程已结束,退出代码0
1.4 互斥锁
import threadingimport time# 定义一个全局变量,用来存储互斥锁trdl = threading.Lock() # 注意Luck首字母要大写def say_hello1(a):# 上锁trdl.acquire()for i in range(10):print('hello', a)time.sleep(0.5)# 解锁trdl.release()def say_hello2(a1, a2):# 上锁trdl.acquire()for i in range(10):print(a1, 'says that hello', a2)time.sleep(0.5)# 解锁trdl.release()def main():b = threading.Thread(target=say_hello1, args=('Peter',))b.start()c = threading.Thread(target=say_hello2, kwargs={'a1': 'Peter', 'a2': 'Joey'})c.start()if __name__ == '__main__':main()
- 在 1.2 的基础上,加上 5/9/14/19/23 行代码,代码会分批执行,现将
say_hello1全部执行完毕,在一口气执行完say_hello2; - 互斥锁的作用是在执行这段代码时,其它线程全部暂停;
- 重复使用互斥锁
trdl.acquire的下场就是程序陷入停顿;
9 参考
【莫烦Python】Threading 学会多线程 Python_哔哩哔哩_bilibili
Python多任务编程 1 线程_哔哩哔哩_bilibili
Python多任务编程 3 互斥锁_哔哩哔哩_bilibili
