线程

队列

队列=管道+锁

from multiprocessing import Queue
​
q = Queue(5)
​
# 注意,这里如果我们在实例化队列这个类的时候给它传值了
# 如果我们向里面添加值得个数超过了这个数字,就会阻塞,
# 如果在向里面添加值,不会报错
# 程序就会,一直卡在这里,指导队列中有数据被取出。
​
q.put(1)  # 向队列中添加值
q.put(1)
q.put(1)
print(q.full())  # 判断队列是否已满,满了返回True,没有满返回False
q.put(1)
q.put(1)
print(q.full())
​
​
q.get()  # 向队列中取出值 注意在队列中已经没有值了。会出现阻塞状态不会报错,直到有值添加到队列中
q.get()
q.get()
print(q.empty())  # 判断队列是否为空,空了返回True,不为空返回False
q.get()
q.get()
q.get_nowait()  # 取值,如果没有就会报错
​
"""
注意;
q.full()
q.empty()
q.get_nowait()
在多进程情况下不能使用,可能会出现偏差
列如;
在多个进程都在取数据的时候,判断了队列为空
但是在你判断过后就有进程添加了值
这个时候就会出现判断不准确
"""

进程间的通信ipc机制

from multiprocessing import Process,Queue
​
​
def func(q):
    # 一个进程给队列添加对象
    q.put("hello")
​
def index(q):
    # 一个进程从对象中取值
    print(q.get())
​
if __name__ == '__main__':
    # 穿件一个队列对象
    q = Queue(5)
    # 创建2个进程,将队列对象传给进程
    p = Process(target=func,args=(q,))
    p1 = Process(target=index,args=(q,))
    p.start()
    p1.start()

  

生产者消费者模式

生产者,生产,生产数据

消费者,消费,处理数据

解决供需不平衡问题

例子;

生产者;生产包子

消费者;吃掉包子

from multiprocessing import Process,JoinableQueue
import random
import time
​
​
def producer(name,food,q):
    for i in range(10):
​
        date = "%s生产了%s,%s"%(name,food,i)
        time.sleep(random.random())
        print(date)
        q.put(date)
        
def consumer(name,q):
    while True:
        time.sleep(random.random())
        date = q.get()
        print("%s吃了%s"%(name,date))
        q.task_done()  # 在取值的地方加上这个方法,告诉队列我已经从里面取出了一个值
​
​
if __name__ == '__main__':
    q = JoinableQueue()  # 创建一个队列对象
    p1 = Process(target=producer,args=("老王","包子",q))
    p2 = Process(target=producer,args=("老张","馒头",q))
    c1 = Process(target=consumer,args=("小王",q))
    c2 = Process(target=consumer,args=("小张",q))
    p1.start()
    p2.start()
    c1.daemon=True  # 将消费者的进程,设置为守护进程,主进程结束,子进程也得结束
    c2.daemon=True
    c1.start()
    c2.start()
    p1.join()  # 确定当我主进程结束,生产者,必须都得执行完
    p2.join()
    q.join()  # 判断我的这个队列是否是取完了,主进程必须得让我的这个子进程中的队列的值取完才能结束
​
​
​
"""
1 我们先得确定生产者必须都得生产完,才能走主进程
2 当生产者生产完了,我们还要判断消费者是否将数据处理完了
即队列中时候还有数值,用task_done()来告诉我们取值情况
这个机制我们不需要了解
3 判断我们这个队列中没有值了
我们将这两个消费者设置为守护进程
我们主进程,子进程也会走完
应为队列的特性是,如果没有值得话,,一直会处于
阻塞态
不会推出循环
"""

线程

什么是线程

注意,线程和进程都是我们虚拟化的,都是来帮我们具体的描述某种事物

线程,执行单位

进程,资源单位

举个列支来帮我们进一步了解线程

将内存比喻工厂

那进程就是工厂中的车间

而线程就是车间中的流水线

 

注意每一个进程都自带一个线程,线程才是执行单位,在执行中所需要的一切资源都来自于进程

所以进程是资源单位

为什么需要线程

进称,需要申请内存空间,拷贝代码,浪费资源

线程,一个进程可以开多个线程,并且线程与线程之间的数据是共享的,开线程的开销,远远比开进程小的多

线程的开启的两种方式

函数

from threading import Thread
​
​
def func():
    pass
​
​
t = Thread(target=func)
t.start()

from threading import Thread
​
class func(Thread):  # 创建类继承Thread
    
    def __init__(self,name):
        super().__init__()
        self.name = name
    def run(self):  # 固定定义这个run方法,规定
        print(self.name)
    
    
t = func("egon")  # 直接实例化我们创建的类对象

线程的其他方法

from threading import Thread,current_thread,active_count
import os
​
​
def func():
    print(current_thread().name) #查看线程号
    print(os.getpid())  # 查看进程号
​
def index():
    pass
​
​
t = Thread(target=func)
t1 = Thread(target=index)
t.daemon=True  # 设置为守护进程
t1.daemon=True   # 设置为守护进程
t.start()
t1.start()
print(active_count())  # 当前活跃的线程数
t.join()  # 主线程等待子线程结束
t1.join()  # 主线程等待子线程结束
print(os.getpid())  # 进程号是一样的

线程之间的通信

线程之间的数据是互相共用的

from threading import Thread
​
​
n = 100
​
def func():
    global n
    n = 999
​
​
t = Thread(target=func)
t.start()
print(n)  # 999
​
​
# 开始n=100
# 修改后n=999

线程互斥锁

from threading import Thread, Lock
import time
​
n = 100
​
​
def func(mutex):
    global n
    mutex.acquire()  # 抢锁
​
    res = n
    time.sleep(0.1)
    n = res - 1
    mutex.release()  # 释放锁
​
​
​
mutex = Lock()
l_list = []
for i in range(100):
    t = Thread(target=func, args=(mutex,))
    t.start()
    l_list.append(t)
​
for j in l_list:
    j.join()
print(n)
date1 = time.time()

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/cherish937426/p/11341028.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值