-
多任务的执行方式:
- 并行:指在同一时刻,有多条指令在多个处理器上同时执行。
- 并发:在一段时间内交替去执行任务。
-
多进程实现多任务一共分为三步走:
-
导入进程包
- import multiprocessing
-
创建子进程并指定执行的任务
- sub_process = multiprocessing.Process (target=任务名)
-
启动进程执行任务
- sub_process.start()
-
-
获取进程编号:
- os.getpid() 表示获取当前进程编号
- os.getppid() 表示获取当前父进程编号
-
进程执行带有参数的任务:
- args 表示以元组的方式给执行任务传参
- kwargs 表示以字典方式给执行任务传参
-
进程的注意点:
- 进程之间不共享全局变量
- 主进程会等待所有的子进程执行结束再结束
-
设置守护进程:
- 为了保证子进程能够正常的运行,主进程会等所有的子进程执行完成以后再销毁,设置守护主进程的目的是主进程退出子进程销毁,不让主进程再等待子进程去执行。
- 设置守护主进程方式: 子进程对象.daemon = True
- 销毁子进程方式: 子进程对象.terminate()
-
多线程实现多任务一共分为三步走:
-
导入线程模块
- import threading
-
创建子线程并指定执行的任务
- sub_thread = threading.Thread(target=任务名)
-
启动线程执行任务
- sub_thread.start()
-
-
线程的注意点:
-
线程执行执行是无序的
-
主线程默认会等待所有子线程执行结束再结束,设置守护主线程的目的是主线程退出子线程销毁。
-
线程之间共享全局变量,好处是可以对全局变量的数据进行共享。
-
线程之间共享全局变量可能会导致数据出现错误问题,可以使用线程同步方式来解决这个问题。
- 线程等待(join)
-
设置守护线程:
- 守护主线程就是主线程退出子线程销毁不再执行
设置守护主线程有两种方式:
- threading.Thread(target=show_info, daemon=True)
- 线程对象.setDaemon(True)
-
-
进程与线程对比:
- 进程和线程都是完成多任务的一种方式
- 多进程要比多线程消耗的资源多,但是多进程开发比单进程多线程开发稳定性要强,某个进程挂掉不会影响其它进程。
- 多进程可以使用cpu的多核运行,多线程可以共享全局变量。
- 线程不能单独执行必须依附在进程里面
1、python中的多进程实现多任务
'''
多进程实现多任务一共分为三步走:
① 导入多进程模块
② 创建子进程
③ 启动进程
'''
import multiprocessing
import time
# 1、创建一个music函数
def music():
for i in range(100):
print('听音乐')
time.sleep(0.2)
# 2、创建一个coding函数
def coding():
for i in range(100):
print('写代码')
time.sleep(0.2)
# 3、编写Python程序的入口
if __name__ == '__main__':
# 在Python程序的入口,会产生一个main主进程
# 4、创建听音乐子进程与写代码的子进程
music_process = multiprocessing.Process(target=music, name='myprocess1')
coding_process = multiprocessing.Process(target=coding)
# 5、启动进程
music_process.start()
coding_process.start()
2、python中获取进程的编号
'''
多进程实现多任务一共分为三步走:
① 导入多进程模块
② 创建子进程
③ 启动进程
'''
import multiprocessing
import time
import os
# 1、创建一个music函数
def music():
print('music:', os.getpid())
print('music:', multiprocessing.current_process())
# 获取父进程ID
print('music的父进程编号:', os.getppid())
for i in range(5):
print('听音乐')
time.sleep(0.2)
# 2、创建一个coding函数
def coding():
print('coding:', os.getpid())
print('coding:', multiprocessing.current_process())
# 获取父进程ID
print('coding的父进程编号:', os.getppid())
for i in range(5):
print('写代码')
time.sleep(0.2)
# 3、编写Python程序的入口
if __name__ == '__main__':
# 在Python程序的入口,会产生一个main主进程
# 获取主进程编号
print('main:', os.getpid())
# 获取主进程信息
print('main:', multiprocessing.current_process())
# 4、创建听音乐子进程与写代码的子进程
music_process = multiprocessing.Process(target=music, name='myprocess1')
coding_process = multiprocessing.Process(target=coding)
# 5、启动进程
music_process.start()
coding_process.start()
3、Python中多进程实现带有参数的多任务
'''
多进程实现多任务一共分为三步走:
① 导入多进程模块
② 创建子进程
③ 启动进程
'''
import multiprocessing
import time
# 1、创建一个music函数
def music(count):
for i in range(count):
print('听音乐')
time.sleep(0.2)
# 2、创建一个coding函数
def coding(count):
for i in range(count):
print('写代码')
time.sleep(0.2)
# 3、编写Python程序的入口
if __name__ == '__main__':
# 在Python程序的入口,会产生一个main主进程
# 4、创建听音乐子进程与写代码的子进程
music_process = multiprocessing.Process(target=music, args=(5,))
coding_process = multiprocessing.Process(target=coding, kwargs={'count':5})
# 5、启动进程
music_process.start()
coding_process.start()
4、Python中进程的注意事项——进程之间不共享全局变量
'''
多进程实现多任务一共分三步:
① 导入模块
② 创建子进程
③ 启动进程
'''
import multiprocessing
import time
# 1、定义一个全局变量
g_list = []
# 2、定义要执行的add_data函数
def add_data():
for i in range(5):
g_list.append(i)
print('add_data:', i)
time.sleep(0.2)
print('add_data:', g_list)
# 3、定义要执行的read_data函数
def read_data():
print('read_data:', g_list)
# 4、定义Python的入口程序
if __name__ == '__main__':
# 创建子进程
add_data_process = multiprocessing.Process(target=add_data)
read_data_process = multiprocessing.Process(target=read_data)
# 启动进程
add_data_process.start()
# join():主进程等待子进程执行结束,在继续执行
add_data_process.join()
read_data_process.start()
# 在主进程中读取g_list
print('main:', g_list)
5、Python中主进程会等待所有子进程结束在结束
'''
进程使用注意点:
① 进程与进程之间不共享全局变量
② 主进程会等待所有子进程结束再结束
'''
import multiprocessing
import time
def task():
for i in range(10):
print('任务执行中...')
time.sleep(0.2)
# 定义Python入口程序
if __name__ == '__main__':
# 创建子进程
sub_process = multiprocessing.Process(target=task)
# 启动子进程
sub_process.start()
# 主进程休眠0.5秒
time.sleep(0.5)
print('over')
# 尝试退出主程序
exit
6、Python中守护主进程与销毁子进程
'''
进程使用注意点:
① 进程与进程之间不共享全局变量
② 主进程会等待所有子进程结束再结束
'''
import multiprocessing
import time
def task():
for i in range(10):
print('任务执行中...')
time.sleep(0.2)
# 定义Python入口程序
if __name__ == '__main__':
# 创建子进程
sub_process = multiprocessing.Process(target=task)
# 解决方案一:把子进程设置为守护主进程
# sub_process.daemon = True
# 启动子进程
sub_process.start()
# 主进程休眠0.5秒
time.sleep(0.5)
print('over')
# 解决方案二:在主程序结束之前强制销毁子进程
sub_process.terminate()
# 尝试退出主程序
exit()
7、Python中多线程实现多任务
'''
Python中多线程实现多任务的三步走:
① 导入模块
② 创建子线程
③ 启动线程
'''
# 1、导入模块
import threading
import time
# 定义music()函数
def music():
for i in range(5):
print('听音乐')
time.sleep(0.2)
# 定义coding()函数
def coding():
for i in range(5):
print('写代码')
time.sleep(0.2)
if __name__ == '__main__':
# 2、创建子线程
music_thread = threading.Thread(target=music)
coding_thread = threading.Thread(target=coding)
# 3、启动线程
music_thread.start()
coding_thread.start()
8、Python中多线程实现带参数的多任务
# 1、导入模块
import threading
import time
# 定义music()函数
def music(count, times):
for i in range(count):
print('听音乐')
time.sleep(times)
# 定义coding()函数
def coding(count, times):
for i in range(count):
print('写代码')
time.sleep(times)
if __name__ == '__main__':
# 2、创建子线程
music_thread = threading.Thread(target=music, args=(5, 0.2))
coding_thread = threading.Thread(target=coding, kwargs={'count':5, 'times':0.2})
# 3、启动线程
music_thread.start()
coding_thread.start()
9、Python中线程之间的执行是没有顺序的
'''
结论:线程与线程之间的执行是没有顺序的
要用到的知识点:threading.current_thread().name => 输出当前线程的信息(名称)
'''
import threading
import time
# 创建要执行的任务
def task():
time.sleep(1)
# 输出线程信息
print('当前线程:', threading.current_thread().name)
# 定义Python入口程序
if __name__ == '__main__':
for _ in range(5):
# 创建子线程
sub_thread = threading.Thread(target=task)
# 启动子线程
sub_thread.start()
10、Python中主线程会等待子线程结束再结束
'''
结论:Python中主线程会等待所有子线程结束再结束
① 创建一个子线程,需要执行2.5s
② 创建一个主线程,需要执行1s
'''
import threading
import time
# 定义要执行的程序
def show_info():
for i in range(5):
print('show_info:', i)
time.sleep(0.5)
# 定义Python入口程序
if __name__ == '__main__':
# 本身拥有一个主线程
# 创建子线程
# ① 守护主线程方案一
# sub_thread = threading.Thread(target=show_info, daemon=True)
sub_thread = threading.Thread(target=show_info)
sub_thread.setDaemon(True)
# 启动子线程
sub_thread.start()
# 主线程休眠1s
time.sleep(1)
print('over')
# 退出程序
exit()
11、Python中线程与线程之间共享全局变量
'''
结论:线程与线程之间可以共享全局变量
'''
import threading
import time
# 定义一个全局变量
my_list = []
# 定义一个写函数,负责向my_list中写入数据
def write_data():
for i in range(5):
my_list.append(i)
time.sleep(0.1)
print('write_data:', my_list)
# 定义一个读函数,负责读取my_list中的数据
def read_data():
print('read_data:', my_list)
if __name__ == '__main__':
write_data_thread = threading.Thread(target=write_data)
read_data_thread = threading.Thread(target=read_data)
# 启动线程
write_data_thread.start()
# 让主线程等待子线程执行完毕后,在继续向下执行
write_data_thread.join()
# 从这个位置开始,真正的读取数据
read_data_thread.start()
12、Python中线程与线程全局变量共享遇到的问题
import threading
import time
# 定义一个全局变量(数字)
g_num = 0
# 定义一个函数(循环100万次,循环累加)
def sum_num1():
for i in range(1000000):
global g_num
g_num += 1
print("sum1:", g_num)
# 定义一个函数(循环100万次,循环累加)
def sum_num2():
for i in range(1000000):
global g_num
g_num += 1
print("sum2:", g_num)
if __name__ == '__main__':
first_thread = threading.Thread(target=sum_num1)
second_thread = threading.Thread(target=sum_num2)
first_thread.start()
# 解决方案:线程同步
first_thread.join()
second_thread.start()