首页 Python教程正文

【教程】并发编程(二)

從出茳湖 Python教程 2019-08-12 20 0


并发编程(二).png并发编程(二)    >>>思维导图>>>博客园

队列

队列:先进先出

堆栈:先进后出

q = Queue(5) 括号内可以传参数:表示的是这个队列的最大存储数

q.put(1) 括号内可以传参数:表示往队列中添加数据,当对列满了,程序会阻塞,直到有人从队列中取走值

q.get():表示向队列取值,当取完后再次获取,程序会阻塞,直到有人往队列存入值

q.full():判断对列是否满了

q.empty():判断队列中的数据是否取完

q.get_nowait():取值,没有值不等待直接报错

full,get_nowait,empty都不适用与多进程的情况

其他方法

q.qsize() 
    返回队列中目前项目的正确数量。此函数的结果并不可靠,因为在返回结果和在稍后程序中使用结果之间,队列中可能添加或删除了项目。在某些系统上,此方法可能引发NotImplementedError异常。
q.close() 
    关闭队列,防止队列中加入更多数据。调用此方法时,后台线程将继续写入那些已入队列但尚未写入的数据,但将在此方法完成时马上关闭。如果q被垃圾收集,将自动调用此方法。关闭队列不会在队列使用者中生成任何类型的数据结束信号或异常。例如,如果某个使用者正被阻塞在get()操作上,关闭生产者中的队列不会导致get()方法返回错误。
q.cancel_join_thread()
    不会再进程退出时自动连接后台线程。这可以防止join_thread()方法阻塞。
q.join_thread() 
    连接队列的后台线程。此方法用于在调用q.close()方法后,等待所有队列项被消耗。默认情况下,此方法由不是q的原始创建者的所有进程调用。调用q.cancel_join_thread()方法可以禁止这种行为。

进程间的通信IPC机制

子进程放数据,主进程获取数据

两个子进程相互放,取数据

from multiprocessing import Process,Queue
def producer(q):
    q.put('hello GF~')
def consumer(q):
    print(q.get())
if __name__ == '__main__':
    q = Queue()
    p = Process(target=producer,args=(q,))
    c = Process(target=consumer, args=(q,))
    p.start()
    c.start()

生产者消费者模型

生产者:生产/制造数据的

消费者:消费/处理数据的

例子:做包子的,买包子的

# 1.做包子远比买包子的多
# 2.做包子的远比包子的少
# 供需不平衡的问题
from multiprocessing import Process,Queue,JoinableQueue
import random
import time
def producer(name,food,q):
    for i in range(10):
        data = '%s生产了%s%s'%(name,food,i)
        time.sleep(random.random())
        q.put(data)
        print(data)
def consumer(name,q):
    while True:
        data = q.get()
        if data == None:break
        print('%s吃了%s'%(name,data))
        time.sleep(random.random())
        q.task_done()  # 告诉队列你已经从队列中取出了一个数据 并且处理完毕了
if __name__ == '__main__':
    q = JoinableQueue()
    p = Process(target=producer,args=('大厨egon','馒头',q))
    p1 = Process(target=producer,args=('跟班tank','生蚝',q))
    c = Process(target=consumer,args=('许兆龙',q))
    c1 = Process(target=consumer,args=('吃货jerry',q))
    p.start()
    p1.start()
    c.daemon = True
    c1.daemon = True
    c.start()
    c1.start()
    p.join()
    p1.join()
    q.join()  # 等到队列中数据全部取出
    # q.put(None)
    # q.put(None)

线程

进程线程其实都是虚拟单位,都是用来帮助我们形象的描述某种事物

进程:资源单位

线程:执行单位

将内存比如成工厂那么进程就相当于是工厂里面的车间而你的线程就相当于是车间里面的流水线ps:每个进程都自带一个线程,线程才是真正的执行单位,进程只是在线程运行过程中提供代码运行所需要的资源

开进程
1.申请内存空间  耗资源2."拷贝代码"    耗资源

开线程
一个进程内可以起多个线程,并且线程与线程之间数据是共享的ps:开启线程的开销要远远小于开启进程的开销

创建进程的两种方式

# 方式一
from threading import Thread
import time
def task(name):
    print('%s is running'%name)
    time.sleep(3)
    print('%s is over'%name)
# 开线程不需要在__main__代码块内     但是习惯性的还是写在__main__代码块内
t = Thread(target=task,args=('egon',))
t.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
# 小的代码执行完 线程就已经开启了
print('主')

# 方式二
from threading import Thread
import time
class MyThread(Thread):
    def __init__(self,name):
        super().__init__()
        self.name = name
    def run(self):
        print('%s is running'%self.name)
        time.sleep(3)
        print('%s is over'%self.name)
t = MyThread('egon')
t.start()
print('主')

线程对象及其他方法

from threading import Thread,current_thread,active_count
import time
import os
def task(name,i):
    print('%s is running'%name)
    # print('子current_thread:',current_thread().name)
    # print('子',os.getpid())
    time.sleep(i)
    print('%s is over'%name)
# 开线程不需要在__main__代码块内 但是习惯性的还是写在__main__代码块内
t = Thread(target=task,args=('egon',1))
t1 = Thread(target=task,args=('jason',2))
t.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
t1.start()  # 告诉操作系统开辟一个线程  线程的开销远远小于进程
t1.join()  # 主线程等待子线程运行完毕
print('当前正在活跃的线程数',active_count())
# 小的代码执行完 线程就已经开启了
print('主')
# print('主current_thread:',current_thread().name)
# print('主',os.getpid())

threading模块

multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性

Thread类的其他方法

Thread实例对象的方法
  # isAlive(): 返回线程是否活动的。
  # getName(): 返回线程名。
  # setName(): 设置线程名。
threading模块提供的一些方法:
  # threading.currentThread(): 返回当前的线程变量。
  # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

join方法

from threading import Thread
import time
def sayhi(name):
    time.sleep(2)
    print('%s say hello' %name)
if __name__ == '__main__':
    t=Thread(target=sayhi,args=('egon',))
    t.start()
    t.join()
    print('主线程')
    print(t.is_alive())
    '''
    egon say hello
    主线程
    False
    '''

守护线程

主线程的结束也就意味着进程的结束

主线程必须等待其他非守护线程的结束才能结束
(意味子线程在运行的时候需要使用进程中的资源,而主线程一旦结束了资源也就销毁了)

from threading import Thread,current_thread
import time
def task(i):
    print(current_thread().name)
    time.sleep(i)
    print('GG')
# for i in range(3):
#     t = Thread(target=task,args=(i,))
#     t.start()
t = Thread(target=task,args=(1,))
t.daemon = True
t.start()
print('主')

线程间通信

from threading import Thread
money = 666
def task():
    global money
    money = 999
t = Thread(target=task)
t.start()
t.join()
print(money)

互斥锁

from threading import Thread,Lock
import time
n = 100
def task(mutex):
    global  n
    mutex.acquire()
    tmp = n
    time.sleep(0.1)
    n = tmp - 1
    mutex.release()
t_list = []
mutex = Lock()
for i in range(100):
    t = Thread(target=task,args=(mutex,))
    t.start()
    t_list.append(t)
for t in t_list:
    t.join()
print(n)

小例子

from threading import Thread
from multiprocessing import Process
import time
def foo():
    print(123)
    time.sleep(1)
    print("end123")
def bar():
    print(456)
    time.sleep(3)
    print("end456")
if __name__ == '__main__':
    t1=Thread(target=foo)
    t2=Thread(target=bar)
    t1.daemon=True
    t1.start()
    t2.start()
    print("main-------")


本文标题:【教程】并发编程(二)
本文链接:https://zhong-er.com/post/62.html
作者授权:除特别说明外,本文由 從出茳湖 原创编译并授权 中二青年 刊载发布。
版权声明:本文使用「署名-非商业性使用-相同方式共享 4.0 国际」创作共享协议,转载或使用请遵守署名协议。

评论

本站会员尊享VIP特权,现在就加入我们吧!登录注册
登录
用户名
密码
注册
用户名
密码
确认密码
邮箱
获取邀请码
邀请码
验证码
找回密码
用户名
邮箱
※ 重置链接将发送到邮箱