多任务

  • 多任务:一个时间内,执行多个任务
  • 多任务的执行方式:
    • 并发:多个任务交替执行(单核 CPU 一定是并发)
    • 并行:在多核CPU中,多个任务在多个CPU上执行

[!tip|style:flat|label:提示]

一般来说,并发和并行是同时存在的,是操作系统自动调度

  • 多任务的实现方式(如何写代码编程实现)
    • 多进程实现
    • 多线程实现
    • 协成实现
  • 时间片:操作系统分配给程序的一小段CPU时间

进程

  1. 进程的介绍

    在Python程序中,想要实现多任务可以使用进程来完成,进程是实现多任务的一种方式。

  2. 进程的概念

    一个正在运行的程序或者软件就是一个进程,它是操作系统进行资源分配的基本单位,也就是说每启动一个进程,操作系统都会给其分配一定的运行资源(内存资源)保证进程的运行

    比如:现实生活中的公司可以理解成是一个进程,公司提供办公资源(电脑、办公桌椅等),真正干活的是员工,员工可以理解成线程。

    [!tip|style:flat|label:提示]

    一个程序运行后至少有一个进程一个进程默认有一个线程,进程里面可以创建多个线程,线程是依附在进程里面的,没有进程就没有线程。

  3. 进程的作用

    [!tip|style:flat|label:提示]

    多进程可以完成多任务,每个进程就好比一家独立的公司,每个公司都各自在运营,每个进程也各自在运行,执行各自的任务。

进程的概念

  • 概念:
    • 程序:安装的程序(QQ,LOL...),写的代码
    • 进程:运行起来的程序就是进程
    • 线程:一个进程中默认会有一个线程,线程是真正执行任务的

多进程的使用

# 导入进程包
import multiprocessing
# Process进程类说明
# Process([group [, target [,name [, args [, kwargs]]]]])
# group: 指定进程组,目前只能使用None
# target:执行的目标任务名
# name:进程名字
# args:以元组方式执行任务传参
# kwargs:以字典方式执行任务传参

# Process创建的实例对象的常用方法
# start():启动子进程实例(创建子进程)
# join():等待子进程执行结束
# terminate():不管任务是否完成,立即终止子进程

# Process创建的实例对象的常用属性
# name:当前的进程的别名。默认Process-N,N为从1开始递增的整数


# 导包
import multiprocessing
import time


def sing():
    for i in range(5):
        print('正在唱歌中....')
        time.sleep(0.1)  # 让进程手动失去CPU资源  让进程休眠0.1秒,今日阻塞态,失去cpu


def dance():
    for i in range(5):
        print('正在跳舞中.....')
        time.sleep(0.1)


if __name__ == '__main__':
    # sing()
    # dance()
    # 创建进程执行的任务,multiprocessing.Process(任务函数名)
    # target 指定执行进程的任务,即函数名字,不能加括号,加括号代表着函数调用,会将函数的返回值返回给target
    process_sing = multiprocessing.Process(target=sing)
    process_dance = multiprocessing.Process(target=dance)
        # 启动进程对象 进程对象.start()
    process_sing.start()
    process_dance.start()

获取进程编号

# 导包
import multiprocessing
import os
import time


def sing():  # 函数定义,主进程执行
    print('sing', multiprocessing.current_process().name, os.getpid(), os.getppid())
    for i in range(5):
        print('正在唱歌中....')
        time.sleep(0.1)  # 让进程手动失去CPU资源  让进程休眠0.1秒,今日阻塞态,失去cpu


def dance():  # 函数定义,主进程执行
    print('dance', multiprocessing.current_process().name, os.getpid(), os.getppid())
    for i in range(5):
        print('正在跳舞中.....')
        time.sleep(0.1)

        # os.kill(进程的id, 9) 杀死进程
        # os.kill(os.getpid(), 9)
        # 第二种写法
        os.kill(multiprocessing.current_process().pid, 9)


if __name__ == '__main__':
    # .name, os.getpid(), os.getppid() 获取名字 和进程的id
    print('main', multiprocessing.current_process().name, os.getpid(), os.getppid())
    # 创建进程执行的任务,即函数名字,不能加括号,加括号代表函数调用,会将返回函数值给target
    process_sing = multiprocessing.Process(target=sing, name='sing')  # 主进程创建子进程 name是修改进程名字
    process_dance = multiprocessing.Process(target=dance)  # 主进程创建子进程

    process_sing.start()
    process_dance.start()

进程的传参

# 导包
import multiprocessing
import os
import time


def sing(singer, song):  # 函数定义,主进程执行
    print('sing', multiprocessing.current_process().name, os.getpid(), os.getppid())
    for i in range(5):
        print(f'{singer}正在唱歌{song}中....')
        time.sleep(0.1)  # 让进程手动失去CPU资源  让进程休眠0.1秒,今日阻塞态,失去cpu


def dance(dancer, name):  # 函数定义,主进程执行
    print('dance', multiprocessing.current_process().name, os.getpid(), os.getppid())
    for i in range(5):
        print(f'{dancer}正在跳{name}舞.....')
        time.sleep(0.1)

        # os.kill(进程的id, 9) 杀死进程
        # os.kill(os.getpid(), 9)
        # 第二种写法
        os.kill(multiprocessing.current_process().pid, 9)


if __name__ == '__main__':
    # .name, os.getpid(), os.getppid() 获取名字 和进程的id
    print('main', multiprocessing.current_process().name, os.getpid(), os.getppid())
    # 创建进程执行的任务,即函数名字,不能加括号,加括号代表函数调用,会将返回函数值给target
    # 进程传参,args 传参 实参是元组  kwargs 传参 实参是字典

    process_sing = multiprocessing.Process(target=sing, name='sing', args=('刘德华', '忘情水'))  # 主进程创建子进程 name是修改进程名字
    process_dance = multiprocessing.Process(target=dance, kwargs={'dancer': '邓丽君', 'name': '万水千山总是情'})  # 主进程创建子进程

    process_sing.start()
    process_dance.start()

进程不共享全局变量

# 导包
import multiprocessing
import time

# 定义全局变量
g_list = []


# 定义任务函数,添加数据,修改变量的值
def add_data():
    for i in range(5):
        g_list.append(i)
        print('添加数据', i)
        time.sleep(0.1)
    # 代码出了 for 循环,代表数据添加完成
    print('add_data', g_list)


#  定义任务函数,都取全局变量的值
def read():
    print('read:', g_list)


if __name__ == '__main__':
    # 创建进程对象
    process_add = multiprocessing.Process(target=add_data)
    process_read = multiprocessing.Process(target=read)

    # 启动进程
    process_add.start()
    # 进程对象.join() 阻塞等待进程完成
    # 谁阻塞等待?代码书写在哪个进程,那个进程阻塞等待
    # 阻塞等待谁执行完成? 那个进程对象.join()就是等待那个进程执行完成
    process_add.join()  # 主进程阻塞等待 2. 等待add进程执行完成
    process_read.start()

主进程会等待子进程执行结束才结束

# 导包
import multiprocessing
import time


# 定义进程所需要执行的任务
def task():
    for i in range(10):
        print('任务执行中...')
        time.sleep(0.5)

    print('子进程代码结束')


if __name__ == '__main__':
    sub_process = multiprocessing.Process(target=task)
    # 方案二,进程设置为 daemon 进程
    sub_process.daemon = True
    sub_process.start()
    time.sleep(1)
    print('主进程的代码结束,理论上程序应该结束')
    # 方案一:进程对象.terminate() 终止进程的执行
    # sub_process.terminate()

results matching ""

    No results matching ""