Python多进程与多线程

一、多进程

1.1 进程的创建步骤

  • 导入进程包

    import multiprocessing

  • 通过进程类创建进程对象
    进程对象 = multiprocessing.Process()

  • 启动进程执行任务
    进程对象.start()

1.2 通过进程类创建进程对象

进程对象 = multiprocessing.Process(target=任务名)

参数名说明
target执行的目标任务名,这里指的是函数名(方法名)
name进程名,一般不用设置
group进程组,目前只能使用None

1.3 进程创建与启动的代码

import multiprocessing
import time


def print1():
    while True:
        time.sleep(3)
        print('11111')


def print2():
    while True:
        time.sleep(3)
        print('22222')


if __name__ == '__main__':
    sing_process1 = multiprocessing.Process(target=print1)
    sing_process2 = multiprocessing.Process(target=print2)
    sing_process1.start()
    sing_process2.start()

1.4 进程执行带有参数的任务

参数名说明
args以元组的方式给执行任务传参
kwargs以字典方式给执行任务传参

1.5 args参数的使用

def print1(s):
    while True:
        time.sleep(3)
        print(s)

if __name__ == '__main__':
	# target: 进程执行的函数名
    # args: 表示以元组的方式给函数传参
    sing_process1 = multiprocessing.Process(target=print1, args=("哈哈哈哈", ))
    sing_process1.start()

1.6 kwargs参数的使用

def print2(s):
    while True:
        time.sleep(3)
        print(s)

if __name__ == '__main__':
	# target: 进程执行的函数名
    # args: 表示以元组的方式给函数传参
    sing_process2 = multiprocessing.Process(target=print2, kwargs={"s": "我是进程2"})
    sing_process2.start()

1.7、获取进程编号

进程编号的作用
当程序中进程的数量越来越多时,如果没有办法区分主进程和子进程还有不同的子进程,那么就无法进行有效的进程管理,为了方便管理实际上每个进程都是有自己编号的。
获取当前进程的编号和父进程的编号:

def work(s):
    while True:
        time.sleep(3)
        # 当前进程的编号(os.getpid())
        print("p1-id:", os.getpid())
        # 父进程的编号 (os.getppid())
        print("p1-pppp", os.getppid())

1.8 、进程的注意点主进程默认会等待所有的子进程执行结束再结束

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lw6dVg2G-1641436802150)(D:\data\projects\gitPro\ZhuBlogHexo\source\images\questions\image-202106241321.png)]

想要主进程结束,子进程也跟着结束,需要设置守护主进程

import multiprocessing
import time


def work():
    while True:
        time.sleep(1)
        print("子进程正在工作中")


if __name__ == '__main__':
    m_work = multiprocessing.Process(target=work)
    # 设置守护
    m_work.daemon = True

    m_work.start()
    time.sleep(3)
    print("主进程结束了")

1.9、多进程实现文件夹多任务白拷贝器

import multiprocessing
import os
import time


class Solution:
    def __init__(self):
        pass

    def copy_file(self, source_path, target_path):
        with open(source_path, "rb") as source_file:
            with open(target_path, "wb") as target_source_file:
                while True:
                    if data := source_file.read():
                        target_source_file.write(data)
                    else:
                        break


def main():
    start_t = time.time()
    source = "D:\\data\\【51优质资源 www.51data.org】算法训练营\\第0课"
    target_source = "E:\\算法训练营"
    source_list = os.listdir(source)
    print(source_list)
    try:
        os.mkdir(target_source)
    except:
        print("文件夹已经存在")
    for path in source_list:
        m = multiprocessing.Process(Solution().copy_file(source + "\\" + path, target_source + "\\" + path))
        m.start()
    end_t = time.time()
    print(end_t - start_t)


if __name__ == '__main__':
    main()

二、多线程

线程介绍 :

  • 多线程是Python程序中实现多任务的一种方式。
  • 线程是程序执行的最小单位
  • 同属一个进程的多个线程**共享进程所拥有的全部资源 **

2.1 实现多任务的另一种形式

在Python中,想要实现多任务还可以使用多线程来完成

2.2 为什么使用多线程?

进程是分配资源的最小单位,一旦创建一个进程就会分配一定的资源,就像跟两个人聊QQ就需要打开两个QQ软件一样是比较浪费资源的。

线程是程序执行的最小单位,实际上进程只负责分配资源,而利用这些资源执行程序的线程,也就说进程是线程的窗口,一个进程中最少有一个线程来负责执行程序,同时线程自己不拥有系统资源,只需要一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源,这就像通过一个QQ软件(一个进程)打开两个窗口(两个线程)跟两个人聊天一样,实现多任务的同时也节省了资源。

2.3 线程的创建步骤

2.3.1 导入线程模块

import threading

2.3.2 通过线程类创建线程对象

线程对象 = threading.Thread(target=任务名)

2.3.3 启动线程执行任务

线程对象.start()

2.4 通过线程类创建线程对象

线程对象=threading.Thread(target=任务名)

参数名说明
target执行的目标任务名,这里指的是函数名(方法名)
name线程名,一般不用设置
group线程组,目前只使用None
import threading
import time


def dance():
    for _ in range(3):
        print("跳舞")
        time.sleep(1)


def sing():
    for _ in range(3):
        print("唱歌")
        time.sleep(1)


if __name__ == '__main__':
    t1 = threading.Thread(target=dance)
    t2 = threading.Thread(target=sing)
    t1.start()
    t2.start()

2.5 线程执行带有参数的任务

参数名说明
args以元组的方式给执行任务传参
kwargs以字典方式给执行任务传参

1、args的使用

import threading
import time

def dance(n):
    for _ in range(n):
        print("跳舞")
        time.sleep(1)
        
if __name__ == '__main__':
    # target:线程执行的函数名
    # args:表示以无组的方式给函数传参,逗号不能丢
    t1 = threading.Thread(target=dance, args=(3, ))

2、kwargs的使用

import threading
import time

def dance(n):
    for _ in range(n):
        print("跳舞")
        time.sleep(1)
        
if __name__ == '__main__':
    # target:线程执行的函数名
    # kwargs:表示以字典的方式给函数传参
    t1 = threading.Thread(target=dance, kwargs={"n": 3})

2.6、主线程和子线程的结束顺序

  • 主线程默认会等待所有子线程执行结束之后再结束 ,除非设置子线程守护主线程
  • 设置守护主线程有两种方式:
    • threading.Thread(target=work, daemon=True)
    • 线程对象.setDaemon(True)

2.7、线程间的执行顺序

线程之间执行是无序的,是由CPU调度决定某个线程先执行的

2.8、多线程实现文件夹多任务白拷贝器

import multiprocessing
import os
import time


class Solution:
    def __init__(self):
        pass

    def copy_file(self, source_path, target_path):
        with open(source_path, "rb") as source_file:
            with open(target_path, "wb") as target_source_file:
                while True:
                    if data := source_file.read():
                        target_source_file.write(data)
                    else:
                        break


def main():
    start_t = time.time()
    source = "D:\\data\\【51优质资源 www.51data.org】算法训练营\\第0课"
    target_source = "E:\\算法训练营"
    source_list = os.listdir(source)
    print(source_list)
    try:
        os.mkdir(target_source)
    except:
        print("文件夹已经存在")
    for path in source_list:
        m = multiprocessing.Process(Solution().copy_file(source + "\\" + path, target_source + "\\" + path))
        m.start()
    end_t = time.time()
    print(end_t - start_t)


if __name__ == '__main__':
    main()

2.9 获取线程id

threading.currentThread().ident

三、进程和线程对比

3.1、关系对比

(1)线程是依附在进程里面的,没有进程就没有线程。

(2)一个进程默认提供一条线程,进程可以创建多个线程。

3.2、区别对比

  1. 创建进程的资源开销要比创建线程的资源开销要大
  2. 进程是操作系统资源分配的基本单位,线程是CPU调度的基本单位
  3. 线程不能够独立执行,必须依存在进程中

3.3、优缺点对比

  1. 进程优缺点:

    • 优点:可以用多核
    • 缺点:资源开销大
  2. 线程优缺点:

    • 优点:资源开销小
    • 缺点:不能使用多核
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值