进程的用法

Hello,大家好。本期来和大家一起学习一下 线程的相关知识。

基础知识补充

64位和32位

32 位和 64 位中的“位”,也叫字长。

字长是 CPU 的主要技术指标之一,指的是 CPU 一次能并行处理的二进制位数

1字节(Byte)=8位(bit/字长/二进制)

64 位的电脑指cpu一次可以处理64个二进制大小的数据

32 位的电脑指cpu一次可以处理32个二进制大小的数据

因此64 位的电脑比32 位的电脑运行速度快。

进程基础知识

概念

进程是操作系统分配资源的基本单位。

一个程序运行起来后,代码与使用到的系统资源被称之为进程。

操作系统工作时,任务数量往往大于cpu的核心数,即一定有一些任务正在执行,而另外一些任务在等待cpu进行执行,因此导致了进程有三种状态:

  • 就绪态:运行的条件都已经具备,正在等待cpu执行

  • 执行态:cpu正在执行其功能

  • 等待态:等待某些条件满足

进程与线程的不同

进程是分配资源;适用场景:需要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。(CPU密集型)

线程是运行程序;适用场景:主要涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。(IO密集型)

一个进程可以创建多少个线程

这和两个因素有关:

  • 每个线程的栈空间(默认为1M)

  • 一个进程中可用的内存空间(默认为2G)

所以理论上一个进程中最多可以开2048个线程

多进程的使用

多进程

python完成多任务,需要使用python的内置包:multiprocessing

1)创建进程对象:

t1 = multiprocessing.Process(target=sing)

2)运行进程:

t1.start()

3)进程等待:

t1.join()

4)获取当前进程的id:

print(os.getpid())

5)获取当前进程的父进程的id:

print(os.getppid())

多进程案例:

import time

import multiprocessing


def test1(a, b, c, *args, **kwargs):
    print(a)
    print(b)
    print(c)
    print(args)
    print(kwargs)


def test2():
    for i in range(10):
        print('222')
        time.sleep(1)


def main():
    # 1.创建进程对象
    """
    在实例化线程对象时,需要指定当前创建的线程对象要运行什么任务?
    通过target参数指定一个任务(地址),args以元组的形式传参,kwargs以字典的形式传参。
    """
    # multiprocessing.set_start_method('fork') 指定当前进程对象启动方式
    p1 = multiprocessing.Process(target=test1, args=(11, 22, 33, 55, 66), kwargs={'name': 'aa'})
    p2 = multiprocessing.Process(target=test2)
    # 2.内部创建进程并运行
    p1.start()
    p2.start()


# 如果大家创建的是一个多进程任务,必须写函数入口,不写报错
if __name__ == '__main__':
    main()

'''
多进程任务在不同的操作系统上创建的进程方向是不一样的
    windows: spawn 必须要写入函数入口
    linux: fork    否则指定当前进程对象启动方式
    macOS: fork    否则指定当前进程对象启动方式

运行结果:
222
11
22
33
(55, 66)
{'name': 'aa'}
222
222
222
...
'''
特点:和线程执行的顺序都是随机的,进程由操作系统自行调度的。

查看进程号案例:

'''
什么是pid:
    一个程序如果在操作系统上被运行之后就变成了一个进程
        操作系统如何找到某一个指定的进程
            借助pid 相当于给进程分配了一个编号
            
linus指令:
-查看当前正在运行的进程:ps aux
-查看某个进程:ps aux|grep "python3"
-杀死某一个进程:kill -9 进程号
'''
import os
import time
import multiprocessing


def test():
    while True:
        # getpid 获取当前进程的id
        # getppid 获取当前进程的父进程的id
        print('子进程 pid=%d, 父进程 pid=%d' % (os.getpid(), os.getppid()))
        time.sleep(1)


def main():
    print('主进程 pid=%d 父进程 pid=%d' % (os.getpid(), os.getppid()))
    p = multiprocessing.Process(target=test)
    p.start()


if __name__ == '__main__':
    main()
'''
运行结果:
主进程 pid=33924 父进程 pid=8768
子进程 pid=34300, 父进程 pid=33924
子进程 pid=34300, 父进程 pid=33924
子进程 pid=34300, 父进程 pid=33924
...
'''

多进程存在的问题

多进程之间不共享全局变量-->通过Queue来实现数据共享(解决办法)

不共享全局变量案例:

import time
import multiprocessing

nums = [11, 22, 33]


def test():
    nums.append(44)
    print('在子进程1中 nums=%s' % str(nums))
    time.sleep(3)


def test2():
    print('在子进程2中 nums=%s' % str(nums))


def main():
    p = multiprocessing.Process(target=test)
    p2 = multiprocessing.Process(target=test2)

    p.start()
    p2.start()


if __name__ == '__main__':
    main()

'''
为什么子进程1中获取的全局变量和子进程2中获取的全局变量的值不一致:
    因为进程是由主进程将当前的资源(代码)拷贝到子进程中
运行结果:
在子进程1中 nums=[11, 22, 33, 44]
在子进程2中 nums=[11, 22, 33]
'''

通过Queue来实现数据共享案例:

'''
模拟一个场景
    进程1 负责下载数据
    进程2 处理数据

使用队列进行数据共享 先进先出
# 队列常用的方法:
# q.empty()  判断队列是否是空的
# q.get()    在队列中取值
# q.put()    在队列中放值
# q.full()   判断队列是否是满的
# q.qsize()  返回队列的大小
'''

import multiprocessing


def download_from_web(q):
    # 模拟下载的数据
    data = [1, 2, 3, 4]
    # 向队列写入数据
    for i in data:
        q.put(i)
    print('下载器下载数据完成并存入队列成功')


def analysis_data(q):
    # 可以获取数据
    waitting_data = list()
    while True:
        data = q.get()
        waitting_data.append(data)
        # bool值  如果队列为空 返回true
        if q.empty():
            break
    print(waitting_data)


def main():
    # 1. 创建队列
    q = multiprocessing.Queue()

    # 2. 创建线程
    p1 = multiprocessing.Process(target=download_from_web, args=(q,))
    p2 = multiprocessing.Process(target=analysis_data, args=(q,))

    p1.start()
    p2.start()


if __name__ == '__main__':
    main()

'''
运行结果:
下载器下载数据完成并存入队列成功
[1, 2, 3, 4]
'''

进程池

学习进程池的原因和线程池是一样的。

我们可以创建一个指定数量的进程池来创建进程,使用到的python第三方库为:

from multiprocessing import Pool

1)创建一个包含3条进程的进程池

po = Pool(3)

2)向进程池提交一个task,i作为worker()函数的参数

po.apply_async(worker, (i,))

3)关闭进程池

po.close()

4)等待进程池中的进程

po.join()

import os
import time
import random
from multiprocessing import Pool


def worker(msg):
    # 创建一个时间对象用来进行任务启动的计时
    t_start = time.time()
    print('%s 开始执行, 进程号: %d' % (msg, os.getpid()))
    # 让当前程序随机休眠 0 - 1
    time.sleep(random.random() * 2)
    t_stop = time.time()
    print(msg, '执行完毕, 耗时: %0.2f' % (t_stop - t_start))


def main():
    # 创建进程池对象
    po = Pool(3)  # 如果任务数大于进程数,则多出来的任务会等待被执行
    for i in range(10):
        # 异步执行的进程任务
        po.apply_async(worker, (i,))
        # 同步执行的进程任务
        # po.apply(worker, (i,)) 一般不用

    print('start......')
    po.close()  # 关闭进程池 当进程池一旦创建并调用close之后 不能动态的去创建进程数量
    po.join()  # 等待进程池中的子进程执行完毕之后 主进程往下执行
    print('end......')


if __name__ == '__main__':
    main()
'''
运行结果:
start......
0 开始执行, 进程号: 10120
1 开始执行, 进程号: 33188
2 开始执行, 进程号: 27816
0 执行完毕, 耗时: 1.39
3 开始执行, 进程号: 10120
2 执行完毕, 耗时: 1.49
4 开始执行, 进程号: 27816
1 执行完毕, 耗时: 1.69
5 开始执行, 进程号: 33188
5 执行完毕, 耗时: 0.62
6 开始执行, 进程号: 33188
3 执行完毕, 耗时: 1.74
7 开始执行, 进程号: 10120
6 执行完毕, 耗时: 0.91
8 开始执行, 进程号: 33188
4 执行完毕, 耗时: 1.99
9 开始执行, 进程号: 27816
7 执行完毕, 耗时: 1.11
8 执行完毕, 耗时: 1.04
9 执行完毕, 耗时: 0.87
end......
'''

关于进程的更多用法,欢迎小伙伴后台留言哦。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值