多任务二(多进程)

进程介绍

  • 进程:通俗理解一个运行的程序或者软件,进程是操作系统资源分配的基本单位。
  • 线程:是程序最小的执行单位。
  • 注意:一个程序至少有一个进程,一个进程至少有一个线程,多进程可以完成多任务.

进程的状态

工作中,任务数往往大于cpu的核数,即一定有一些任务正在执行,而另外一些任务在等待cpu进行执行,因此导致了有了不同的状态。

在这里插入图片描述
就绪态:运行的条件都已经慢去,正在等在cpu执行
执行态:cpu正在执行其功能
等待态:等待某些条件满足,例如一个程序sleep了,此时就处于等待态

多进程完成多任务

  • 导入进程模块

#导入线程模块
import multiprocessing

  • Process进程类的语法结构如下:
  • Process([group [, target [, name [, args [, kwargs]]]]])
    group:指定进程组,目前只能使用None
    target:执行的目标任务名
    name:进程名字
    args:以元组方式给执行任务传参
    kwargs:以字典方式给执行任务传参
  • Process创建的实例对象的常用方法:
    start():启动子进程实例(创建子进程)
    join([timeout]):是否等待子进程执行结束,或等待多少秒
    terminate():不管任务是否完成,立即终止子进
  • Process创建的实例对象的常用属性:
    name:当前进程的别名,默认为Process-N,N为从1开始递增的整数
    pid:当前进程的pid(进程号)

进程注意点

  • 进程之间不共享全局变量(注意:创建子进程其实是对主进程进行拷贝,进程之间相互独立,访问的全局变量不是同一个,所以进程之间不共享全局变量)

一个进程中地址是唯一的,不同的进程可以有相同的地址
程序唯一确定的一个地址中根据进程的编号+进程内的地址

  • 主进程会等待所有子进程执行完成程序再退出

进程,线程对比:

  • 1、功能对比
  • 进程,能够完成多任务,比如 在一台电脑上能够同时运行多个QQ
  • 线程,能够完成多任务,比如 一个QQ中的多个聊天窗口
  • 2、定义对比
  • 进程是系统进行资源分配基本单位,每启动一个进程操作系统都需要为其分配运行资源。
  • 线程是运行程序中的一个执行分支,是CPU调度基本单位。
  • 总结:进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
  • 3、关系对比
  • 线程是依附在进程里面的,没有进程就没有线程
  • 一个进程默认提供一条线程,进程可以创建多个线程
  • 4、区别
  • 进程之间不共享全局变量
  • 线程之间共享全局变量,但是要注意资源竞争的问题,解决办法: 互斥锁或者线程同步
  • 创建进程的资源开销要比创建线程的资源开销要大
  • 进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
  • 线程不能够独立执行,必须依存在进程中
  • 多进程开发比单进程多线程开发稳定性要强
  • 5、优缺点
  • 多进程:
    优点:可以用多核
    缺点:资源开销大多
  • 线程:
    优点:资源开销小
    缺点:不能使用多核

代码实例

一边唱歌一边传参进程版传参

# 一边唱歌一边跳舞
import threading
import multiprocessing  # 多进程模块
import time


def dance(name):
    # 打印
    print("dance:", multiprocessing.current_process().name)
    print("dance:", threading.current_thread().name)
    while True:
        print("跳舞", name)
        time.sleep(1)


def test():
    while True:
        print("子进程开线程")
        time.sleep(1)


def song(name):
    # 开一个线程
    threading.Thread(target=test).start()

    # 打印
    print("song:", multiprocessing.current_process().name)
    print("song:", threading.current_thread().name)
    while True:
        print("唱歌", name)
        time.sleep(1)


def main():
    """一边唱歌一边跳舞"""
    # # 开启线程
    # threading.Thread(target=dance,args=("小班",)).start()
    # threading.Thread(target=song,kwargs={"name":"小班"}).start()

    # 开启进程
    multiprocessing.Process(target=dance, args=("小班",)).start()
    multiprocessing.Process(target=song, kwargs={"name": "小班"}).start()

    # 打印
    print("main:", multiprocessing.current_process().name)
    print("main:", threading.current_thread().name)


if __name__ == '__main__':
    main()

运行结果

main: MainThread
dance: Process-1
dance: MainThread
跳舞 小班
子进程开线程
song: Process-2
song: MainThread
唱歌 小班
跳舞 小班
子进程开线程
唱歌 小班

队列的使用

# 队列的作用:让进程之间进行通讯
# 使用的队列,创建,放数据,取数据

# 队列中的数据,如果取了,那么这个数据就没有了
# 队列先进先出
import multiprocessing

# 创建队列
queue = multiprocessing.Queue(3)  # 队列中最多放三个,如果不写,那么内存大小
# 放入数据
queue.put("123")
queue.put("abc")

queue.put("abc")
# queue.put("abc") # 堵塞了,如果数据超过队列的最大值,会等待

# 取数据
print(queue.get())
print(queue.get())
print("个数:", queue.qsize())
print(queue.get())
# print(queue.get()) # 堵塞了,如果队列的数据为空了,那么会等待

print("取完了")

使用队列实现进程间数据共享

# 使用队列进行进程间的数据共享


# 定义一个队列
import multiprocessing
import time

# 定义一个队列
queue = multiprocessing.Queue(3)

# 一个读一个写
# 写
def write():
    for temp in range(100):
        queue.put(temp)
        time.sleep(1)

# 读
def read():
    for temp in range(100):
        print("读:", queue.get())
        time.sleep(1)

def main():
    """进程之间数据共享使用队列"""
    # 使用进程去创建任务
    multiprocessing.Process(target=write).start()
    multiprocessing.Process(target=read).start()

if __name__ == '__main__':
    main()

进程池

同步进程池(任务一个执行完再执行下一个)

# 进程池的作用是用来复用进程

# 复制文件
import os
import time

# 复制
import multiprocessing


def copy():
    print("复制开始", os.getpid())
    time.sleep(1)
    print("复制结束", os.getpid())


def main():
    """用进程池使用"""

    # 创建进程池`在这里插入代码片`
    pool = multiprocessing.Pool(3)  # 会创建3个进程
    # 循环复制文件
    for temp in range(5):
        # 把任务加入到进程池中
        pool.apply(copy)  # 同步进程池

    
if __name__ == '__main__':
    main()

异步进程池(任务同时去执行)

# 进程池的作用是用来复用进程


# 复制文件
import os
import time

# 复制
import multiprocessing


def copy():
    print("复制开始", os.getpid())
    time.sleep(4)
    print("复制结束", os.getpid())


def main():
    """用进程池使用"""

    # 创建进程池同步,一个任务结束,下一个开始
    pool = multiprocessing.Pool(3)  # 会创建3个进程
    # 循环复制文件
    for temp in range(5):
        # 把任务加入到进程池中
        pool.apply_async(copy)  # 异步进程池

    # 让他等待
    pool.close()  # 进程池不在添加新的任务了
    pool.join()  # 让主进程等待进程池的操作结束以后再运行下面的代码

    print("主进程结束")


if __name__ == '__main__':
    main()

使用进程复制一个简单的文件夹

# 复制文件夹
# 1.创建一个新的文件
# 2. 遍历以前要复制文件夹中的内容
# 3. 循环去复制文件
# 4. 复制:打开文件,读取文件,写入到新文件
import os

import shutil

import multiprocessing


def copy_file(copy_file_before, copy_file_after):
    """复制"""
    # 4. 复制:打开文件,读取文件,写入到新文件
    # 打开
    with open(copy_file_before, 'rb') as f:
        content = f.read()

    # 写入
    with open(copy_file_after, 'wb') as f:
        f.write(content)


def main():
    """文件夹复制"""

    # 1.创建一个新的文件
    # 判断当前的文件夹是否存在,如果存在,那么删除
    if os.path.exists('./works_back'):
        # 说明存在,删除 文件夹,一定要注意 这个文件夹有可能是非空的
        shutil.rmtree("./works_back")  # 删除 非空的文件夹
    # 创建文件夹
    os.mkdir("./works_back")

    # 2. 遍历以前要复制文件夹中的内容
    files = os.listdir("./works")
    print(files)

    # 3. 循环去复制文件
    for temp in files:
        # 复制文件
        # copy_file(要复制文件的路径,要保存文件的路径)
        # 要复制文件的路径
        copy_file_before = "./works/%s" % temp
        # 要保存文件的路径
        copy_file_after = "./works_back/%s" % temp
        # 复制
        # copy_file(copy_file_before, copy_file_after)
        multiprocessing.Process(target=copy_file, args=(copy_file_before, copy_file_after)).start()


if __name__ == '__main__':
    main()

协程版本

# gevent这个是我们的解释器切换

# 复制文件夹
# 复制文件夹
# 1.创建一个新的文件
# 2. 遍历以前要复制文件夹中的内容
# 3. 循环去复制文件
# 4. 复制:打开文件,读取文件,写入到新文件


# 协程使用
# 1. 导入模块
# 2. 打补丁
# 3. 加入任务列表
# 4. 等待

import os

import shutil

import multiprocessing

# 导入模块
import gevent

from  gevent import monkey

# 打补丁
monkey.patch_all()


def copy_file(copy_file_before, copy_file_after):
    """复制"""
    # 4. 复制:打开文件,读取文件,写入到新文件
    # 打开
    with open(copy_file_before, 'rb') as f:
        content = f.read()

    # 写入
    with open(copy_file_after, 'wb') as f:
        f.write(content)


def main():
    """文件夹复制"""

    # 1.创建一个新的文件
    # 判断当前的文件夹是否存在,如果存在,那么删除
    if os.path.exists('./works_back'):
        # 说明存在,删除 文件夹,一定要注意 这个文件夹有可能是非空的
        shutil.rmtree("./works_back")  # 删除 非空的文件夹
    # 创建文件夹
    os.mkdir("./works_back")

    # 2. 遍历以前要复制文件夹中的内容
    files = os.listdir("./works")
    print(files)

    # 创建一个gevent等待的列表
    gevent_list = list()

    # 3. 循环去复制文件
    for temp in files:
        # 复制文件
        # copy_file(要复制文件的路径,要保存文件的路径)
        # 要复制文件的路径
        copy_file_before = "./works/%s" % temp
        # 要保存文件的路径
        copy_file_after = "./works_back/%s" % temp
        # 复制
        # copy_file(copy_file_before, copy_file_after)
        # 加入任务
        gevent_list.append(gevent.spawn(copy_file, copy_file_before, copy_file_after))

    # 让我们的协程等待
    gevent.joinall(gevent_list)


if __name__ == '__main__':
    main()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值