python的队列和进程

提示:文章基本为自己实验总结,仅参考,可能有不严谨的地方请读者们见谅


前言

线程优先级队列( Queue):

Python的Queue模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列PriorityQueue。这些队列都实现了锁原语,能够在多线程中直接使用。可以使用队列来实现线程间的同步。
Python线程


提示:以下是本篇文章正文内容,下面案例可供参考
进程就是正在运行的程序的实例。

进程是具有一定独立功能的程序,它会关于某个数据进行运行活动。

进程是一个实体,都会有自己的地址空间,里面有文本区域,数据区域,堆栈。

一、 Queue队列基本基础

为了方面之后进程的数据交互,所以要学习队列

Queue模块中的常用方法:

Queue.qsize() 返回队列的大小
Queue.empty() 如果队列为空,返回True,反之False
Queue.full() 如果队列满了,返回True,反之False
Queue.full 与 maxsize 大小对应
Queue.get([block[, timeout]])获取队列,timeout等待时间
Queue.get_nowait() 相当Queue.get(False)
Queue.put(item, block=True, timeout=None) 写入队列,timeout等待时间
Queue.put_nowait(item) 相当 Queue.put(item, False)
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
Queue.join() 实际上意味着等到队列为空,再执行别的操作

put_nowait

q.put_nowait("x4")#可以用put_nowait,如果队列满了就不会堵塞,但是会报错。。。

full()和empty()

 print(q.full())#判断一下队列是否满了
 print(q.empty())#判断一下队列是为空

实例如下👇

import time,os,random
from multiprocessing import Process,Queue


def main():
    q = Queue(3)#定义一个叫q的队列,队列容量为3
    q.put("x1")
    q.put("x2")
    q.put("x3")

    # q.put("x4"),如果队列满了程序就会停在这里,等待数据被人取走,再将数据放入队列

    try:
        q.put_nowait("x4")#可以用put_nowait,如果队列满了就不会堵塞,但是会报错。。。
    except:
        print("队列满了,不能再放了")

    print(q.full())#判断一下队列是否满了
    print(q.get())
    print(q.get())
    print(q.get())
    print(q.empty())#判断一下队列是为空



    pass

if __name__=='__main__':
    main()

pycharm显示结果为:

队列满了,不能再放了
True
x1
x2
x3
True

Process finished with exit code 0

二、进程间传递数据—队列

使用queue实现进程之间的信息传递

在编程中,我们经常需要在不同的进程之间传递数据。就像我们在梦中经历的事件可以在清醒状态下回忆一样,进程之间也需要一个类似的中介来共享数据。这个中介就是队列(Queue)对象,在Python的multiprocessing包中有一个专门的Queue类用于实现这个目的。

你可以把队列想象成排队的人群,按照先来后到的原则,数据被依次放入队列中。不同的进程可以从队列中取出数据,并将自己的数据放入其中,以便其他进程使用。这样,进程之间就能够方便地共享数据了。

使用队列作为中介的好处是,它提供了一种安全和同步的方式来传递数据。多个进程可以同时读写队列,而不需要担心数据错乱或冲突的问题。队列会按照先进先出的原则确保数据被正确地交换和传递。

总结来说,队列是进程之间数据传递的一种有效方式。它类似于一个中介,让不同的进程能够按照一定规则共享数据,实现数据交换和通信。

以下用三个实例说明进程队列间传递数据
生产者和消费者模型

实例一

import time,os,random
from multiprocessing import Process,Queue

def customer(q):
    while True:
        res = q.get()
        if res is None: break
        time.sleep(random.randint(1,3))
        print("%s 吃了 %s"%(os.getpid(),res))


def producer(q):
    for i in range(10):
        time.sleep(random.randint(2,4))
        res = "包子 %s"%(i)
        q.put(res)
        print("%s生产了%s"%(os.getpid(),res))
    q.put(None)

def main():
    q = Queue()
    p1 = Process(target=customer,args=(q,))
    p2 = Process(target=producer,args=(q,))
    p1.start()
    p2.start()
    print("主进程开始")

    pass

if __name__=='__main__':
    main()


运行结果为:
在这里插入图片描述

实例二

import time,os,random
from multiprocessing import Process,Queue

#结束信号None,不一定只能由生产者去发,可以主进程等生产者完成后由主进程去发


def customer(q):
    while True:
        res = q.get()
        if res is None: break
        time.sleep(random.randint(1,3))
        print("%s 吃了 %s"%(os.getpid(),res))


def producer(q):
    for i in range(10):
        time.sleep(random.randint(2,4))
        res = "包子 %s"%(i)
        q.put(res)
        print("%s生产了%s"%(os.getpid(),res))


def main():
    q = Queue()
    p1 = Process(target=customer,args=(q,))
    p2 = Process(target=producer,args=(q,))
    p1.start()
    p2.start()
    p1.join()
    q.put(None)
    print("主进程开始")

    pass

if __name__=='__main__':
    main()



运行结果为:

28852生产了包子 0
23028 吃了 包子 0
28852生产了包子 1
23028 吃了 包子 1
28852生产了包子 2
28852生产了包子 3
23028 吃了 包子 2
28852生产了包子 4
23028 吃了 包子 3
28852生产了包子 5
23028 吃了 包子 4
23028 吃了 包子 5
28852生产了包子 6
23028 吃了 包子 6
28852生产了包子 7
23028 吃了 包子 7
28852生产了包子 8
28852生产了包子 9
23028 吃了 包子 8
23028 吃了 包子 9

实例三:多个生产者和消费者

import time,os,random
from multiprocessing import Process,Queue




def customer(q):
    while True:
        res = q.get()
        if res is None: break
        time.sleep(random.randint(1,3))
        print("%s 吃了 %s"%(os.getpid(),res))


def producer(name,q):
    for i in range(10):
        time.sleep(random.randint(2,4))
        res = "%s 的 %s号"%(name,i)
        q.put(res)
        print("%s生产了%s"%(os.getpid(),res))


def main():
    q = Queue()
    #多个厨师
    p1 = Process(target=producer,args=("包子",q,))
    p2 = Process(target=producer,args=("牛肉",q,))
    p3 = Process(target=producer,args=("骨头",q,))

    #多个消费者
    c1 = Process(target=customer,args=(q,))
    c2 = Process(target=customer,args=(q,))

    p1.start()
    p2.start()
    p3.start()

    c1.start()
    c2.start()
    #必须保证生产者都处理完毕,才能发出结束信号
    p1.join()
    p2.join()
    p3.join()

    #有几个消费者发出几个结束信号
    q.put(None)
    q.put(None)
    q.put(None)

    print("主进程开始")

    pass

if __name__=='__main__':
    main()

运行结果为:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


三、共享进程队列

from multiprocessing import Process,Queue,JoinableQueue

JoinableQueue:
是一个创建可连接的共享进程队列,它其实相当于Queue的一个对象队列形式,它允许项目的使用者通知生产者:项目已经被处理了。
JoinableQueue 主要用于生产者消费者模型,解决多个消费者在消费完队列中所有任务后结束消费进程
JoinableQueue 却别于 Queue的两个主要方法:

1、task_done() 使用此方法发出当前队列中取出来的项目已经被处理(消费者调用此方法)

2、join() 生产者调用此方法进行阻塞,直到JoinableQueue 中的每个项目都收到了task_done()处理完成的消息 才会停止阻塞

实例

本例中较重要的两个函数👇

q.task_done()#向q.join发送一次信号,证明数据已经被取走了
q.join()#生产完毕,使用这个方法进行阻塞,直到队列中所有内容被处理
import time,os,random
from multiprocessing import Process,Queue,JoinableQueue



def customer(q):
    while True:
        res = q.get()
        time.sleep(random.randint(1,3))
        print("%s 吃了 %s"%(os.getpid(),res))
        q.task_done()#向q.join发送一次信号,证明数据已经被取走了



def producer(name,q):
    for i in range(10):
        time.sleep(random.randint(2,4))
        res = "%s 的 %s号"%(name,i)
        q.put(res)
        print("%s生产了%s"%(os.getpid(),res))

    q.join()#生产完毕,使用这个方法进行阻塞,直到队列中所有内容被处理


def main():
    q = JoinableQueue
    #定义生产者们
    p1 = Process(target=producer, args=("包子", q))
    p2 = Process(target=producer, args=("羊肉", q))
    p3 = Process(target=producer, args=("猪肉", q))

    #定义消费者们
    c1 = Process(target=customer,args=(q,))
    c2 = Process(target=customer, args=(q,))

    #设置为守护进程
    c1.daemon = True
    c2.daemon = True

    #开始
    p_1 = [p1,p2,p3,c1,c2]
    for p in p_1:
        p.start()

    p1.join()
    p2.join()
    p3.join()
    print("主进程")

    pass

if __name__=='__main__':
    main()

本实例流程白话简介:

在这里插入图片描述
运行结果为:

17392生产了包子 的 022716生产了猪肉 的 013116 吃了 猪肉 的 07580生产了羊肉 的 017392生产了包子 的 122716生产了猪肉 的 123616 吃了 包子 的 013116 吃了 羊肉 的 07580生产了羊肉 的 123616 吃了 包子 的 113116 吃了 猪肉 的 122716生产了猪肉 的 213116 吃了 猪肉 的 217392生产了包子 的 223616 吃了 羊肉 的 17580生产了羊肉 的 213116 吃了 包子 的 223616 吃了 羊肉 的 222716生产了猪肉 的 313116 吃了 猪肉 的 317392生产了包子 的 37580生产了羊肉 的 323616 吃了 包子 的 313116 吃了 羊肉 的 317392生产了包子 的 422716生产了猪肉 的 47580生产了羊肉 的 423616 吃了 包子 的 413116 吃了 猪肉 的 417392生产了包子 的 522716生产了猪肉 的 57580生产了羊肉 的 513116 吃了 包子 的 523616 吃了 羊肉 的 47580生产了羊肉 的 613116 吃了 猪肉 的 517392生产了包子 的 622716生产了猪肉 的 623616 吃了 羊肉 的 57580生产了羊肉 的 713116 吃了 羊肉 的 617392生产了包子 的 77580生产了羊肉 的 823616 吃了 包子 的 622716生产了猪肉 的 713116 吃了 猪肉 的 623616 吃了 羊肉 的 717392生产了包子 的 822716生产了猪肉 的 823616 吃了 羊肉 的 87580生产了羊肉 的 913116 吃了 包子 的 717392生产了包子 的 922716生产了猪肉 的 923616 吃了 猪肉 的 713116 吃了 包子 的 823616 吃了 猪肉 的 813116 吃了 羊肉 的 913116 吃了 猪肉 的 923616 吃了 包子 的 9号
主进程

Process finished with exit code 0


四、进程

进程是一个执行中的程序,资源分配的最小单位。每个进程都拥有自己的地址空间、内存、数据栈以及其他用于跟踪执行的辅助数据。在单核CPU系统中的多进程,内存中可以有许多程序,但在给定一个时刻只有一个程序在运行;就是说,可能这一秒在运行进程A,下一秒在运行进程B,虽然两者都在内存中,都没有真正同时运行。

进程是一个实体,都会有自己的地址空间,里面有文本区域,数据区域,堆栈。

文本区域:存储cpu执行的代码
数据区域:执行一些存储变量,动态分配的内存
堆栈:存储在活动过程中调用的指令和变量这些

进程具有动态性:会动态产生和动态消亡
并发性

独立性

异步性:有些进程是相互制约的,而且它会有间歇性,堵塞呀之类的

实例

import time,os,random
import multiprocessing

def test1(a):
    print("test1 start",a)
    print("test1的进程id为:",os.getpid())#查看当前进程id
    print("test1的父进程id为:",os.getppid())#查看当前父进程id
    time.sleep(1)

def test2(a):
    print("test2 start",a)
    print("test2的进程id为:",os.getpid())#查看当前进程id
    print("test2的父进程:",os.getppid())#查看当前父进程id
    time.sleep(1)

def main():
    print("main函数的进程id为:",os.getpid())
    #创建进程
    t1 = multiprocessing.Process(target=test1,args=("hello",))
    t2 = multiprocessing.Process(target=test2,args=("world",))
    #启动进程
    t1.start()
    t2.start()
    print("haha")


    pass

if __name__=='__main__':
    main()

运行结果为:

main函数的进程id为: 22664
haha
test1 start hello
test1的进程id为: 24924
test2 start world
test2的进程id为: 18556
test1的父进程id为: 22664
test2的父进程: 22664

Process finished with exit code 0

五、并发系列process学习

进程调度:

1、先来先服务算法:利用长作业的进程,适合cpu繁忙的作业,而不是io繁忙的作业
2、短作业优先调度算法:不能保证紧急的作业被完成
3、时间片轮转:将cpu的处理时间分成固定大小的时间片,分为几百毫秒,几十毫秒这种。。。。
调度分配一些可以抢占的资源,可以分配和收回

程序的状态:

就绪状态,执行/运行状态,阻塞状态
process进程是一个资源分配的总和,线程是拿资源去执行

多进程多任务是多个资源每个资源至少一个人做事

多线程多任务是一个资源多个人做事

实例一

import time,os,random
from multiprocessing import Process

def p(name):
    print("hello",name)
    print("子进程")
    time.sleep(1)



def main():
    p1 = Process(target=p,args=("xiaoming",))
    p1.start()
    print("主进程")


    pass

if __name__=='__main__':
    main()

运行结果为:

主进程
hello xiaoming
子进程

Process finished with exit code 0

如果需要把上述↑的实例中,子进程做五次呢?

实例二

import time,os,random
from multiprocessing import Process

def p(name):
    print("hello",name)
    print("子进程")
    time.sleep(1)



def main():
    p_list = []
    for i in range(5):
        p1 = Process(target=p,args=("小明",))
        p1.start()
        p_list.append(p1)

    print(p_list)
    print("主进程")

    pass

if __name__=='__main__':
    main()

运行结果为:

主进程
hello 小明
子进程
hello 小明
子进程
hello 小明
子进程
hello 小明
子进程
hello 小明
子进程

Process finished with exit code 0

那再如果想让一个事情先做,然后间隙中又去做另一个事呢?,而且他们都是子进程,该怎么办呢?

实例三

import time,os,random
from multiprocessing import Process

def test1():
    print("test1 start")
    time.sleep(5)
    print("test1 stop")

def test2():
    print("test2 start")
    time.sleep(2)
    print("test2 stop")


def main():
    print("main start")
    t1 = Process(target=test1)
    t2 = Process(target=test2)

    t1.start()
    t2.start()
    print("main stop")



    pass

if __name__=='__main__':
    main()

运行结果为:

main start
main stop
test1 start
test2 start
test2 stop
test1 stop

Process finished with exit code 0

join:阻塞当前进程,直到调用join的方法的进程执行完,再继续执行当前进程

实例四

import time,os,random
from multiprocessing import Process

def test1():
    print("test1 start")
    time.sleep(5)
    print("test1 stop")

def test2():
    print("test2 start")
    time.sleep(2)
    print("test2 stop")


def main():
    print("main start")
    t1 = Process(target=test1)
    t2 = Process(target=test2)

    t1.start()
    t2.start()
    t1.join()
    print("main stop")



    pass

if __name__=='__main__':
    main()

结果运行为:

main start
test1 start
test2 start
test2 stop
test1 stop
main stop

Process finished with exit code 0

六、守护进程

守护进程就是Daemon程序,是一种在系统后台执行的程序,它独立于控制终端并且执行一些周期任务或触发事件,通常被命名为"d"字母结尾,如常见的httpd、syslogd、systemd和dockerd等。

实例

守护进程一定要在start之前开启,设置True就是守护进程开始(但是p2没有开守护进程可以一直执行下去)
在父进程代码结束之后,守护进程立马停止运行

import time,os,random
from multiprocessing import Process

def test1():
    print("test1 start")
    time.sleep(1)
    print("test1 stop")

def test2():
    print("test2 start")
    time.sleep(5)
    print("test2 stop")


def main():
    print("main start")

    p1 = Process(target=test1)
    p2 = Process(target=test2)

    p1.daemon = True #开启守护进程
    p1.start()
    p2.start()

    time.sleep(0.1)
    print("main stop")


    pass

if __name__=='__main__':
    main()

运行结果为:
没有test1 stop,因为父进程结束了

main start
test1 start
test2 start
main stop
test2 stop

Process finished with exit code 0

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值