zoukankan      html  css  js  c++  java
  • 线程


    !!!不要高估自己!!!

    昨日内容回顾:
    进程理论
    操作系统的调度算法
    时间片轮转法
    多级反馈队列
    同步异步:任务的提交方式

    同步:提交任务后原地等待任务的返回结果,才能进行下一步操作
    异步:提交任务后不等待任务的返回结果,直接执行下一步操作

    阻塞非阻塞:程序的执行状态
    阻塞:阻塞态
    非阻塞:运行或就绪态

    需要掌握的是程序运行的三状态图


    进程:正在运行的程序
    多道技术:
    空间上的复用
    多个程序公用一套硬件设备
    时间上的复用
    CPU的来回切换:切换+保存状态
    --程序占用CPU时间过长,会被操作系统强行剥夺走CPU执行权限
    --程序接入io操作
    input
    网络请求 recv accept
    time.sleep
    文件读写
    print

    创建进程的两种方式(本质:在内存中申请一块独立的内存空间!!!)
    windows下创建进程内部实现:以模块导入的方式,将代码copy到新申请的内存空间中

    1.自己定义一个函数,调用Process传参(target=’自己写的函数名‘,args=(v1,))
    2.写一个类,继承Process,在里面固定写一个run方法


    创建进程的开销比较大
    1.申请内存空间
    2.拷贝代码

    join方法

    让主进程等待子进程程序运行结束,不会影响子进程的执行过程!
    会将并发变成串行

    进程间数据是相互隔离的
    如何验证:开一个子进程,修改主进程里面的数据,发现根本无法修改

    进程对象的其他方法
    查看进程id号
    current_process().pid >>Process().pid
    os.getpid()

    terminate() 主动发起杀死进程的操作
    time.sleep(0.1)
    is_alive() 判断进程是否存活

    僵尸进程和孤儿进程
    子进程结束后不会立即释放pid等资源信息
    主进程释放子进程资源的两种情况:
    主进程正常死亡
    join方法
    任何进程都会步入僵尸进程,当主进程不停的创建子进程的时候会有害
    孤儿进程:主进程意外死亡
    在Linux中有一个init,来帮我们回收孤儿进程资源

    守护进程
    主进程一旦运行完毕,子进程立即结束运行(唇亡齿寒)

    互斥锁

    为了保证多个程序操作同一份数据数据安全,而设置的一把锁(四人抢厕所)

    如何创建锁:
    from multiprocessing import Lock
    mutex=Lock()

    #抢锁
    mutex.acquire()
    #释放锁
    mutex.release()

    会将并发变成串行,虽然牺牲了效率,但是提高了数据的安全性

    #注意:不要随意的加锁,只会在操作数据的部分加锁


    模拟抢票

    今日内容:
    进程间通信IPC机制
    队列:先进先出
    堆栈:先进后出
    本来进程之间是完全无法通信的,但是可以通过认为的干预,让他们实现通信
    multiprocessing 中有一个组件Queue,就可以实现两个进程之间的通信
    q=Queue()#一个实例化对象
    q.put()#不写参数默认接收好多个
    q.put(5)#接收5个数据
    q.put()#多放一个会出现阻塞,会一直在原地等待
    q.full()#判断队列是否满了!
    q.get()#取数据,get一次就是取一次
    q.get_nowait()#如果超过了存放的数据,会报错queue.empty
    q.get()#如果超过了存放的数据,会一直在原地等待数据传过来,会出现阻塞
    q.empty()#判断进程是否为空,但是在并发的情况下这个判断的并不准确
    可能一个数据刚产生就被拿走,判断为空,但是下一秒又会满


    #基于队列实现线程间通信
    from multiprocessing import Process

    def producer(q):
    q.put('hello')

    def constumer(q):
    print(q.get())


    if __name__=='__main__':
    q=Queue()
    p=Process(target=producer,args=(q,))
    c=Process(target=constumer,args(q,))
    p.start()
    c.start()

    #队列:先进先出
    #堆栈:先进后出
    #基于队列实现进程间通信
    from multiprocessing import Queue

    q=Queue(5) #产生一个队列 就相当于产生了一个容器 ()不写参数,可以放好多个
    # a=Queue(5) #产生一个最多能够存放五个的数据的队列

    # q.put(1)
    # q.put(2)
    # q.put(3)
    # print(q.full())
    # q.put(4)
    # q.put(5)
    # # q.put(6)#往队列中存放数据,如果存放的数据个数大于队列最大存储个数,程序会阻塞
    # print(q.full()) #判断队列是否满了?


    # for i in range(6):
    # q.put(i) #也夯住了

    #存取数据,侧重点是取!!
    for i in range(5):
    q.put(i) #for循环往队列里面存放数据
    print(q.get())#取数据,get一次就是取一次
    print(q.get())
    print(q.get())
    q.get_nowait() #在队列有数据的情况下和get取值一样,当队列没有数据的情况下,取值直接报错
    print(q.empty()) #判断队列是否为空,需要注意的是在并发的情况下这个方法不准确
    print(q.get())
    print(q.get())
    print(q.empty())
    # q.get_nowait() #queue.Empty
    # print(q.get())#如果队列为空,get会在原地等待队列中数据传过来

    基于队列实现进程间通信
    from multiprocessing import Process,Queue


    def producer(q):
    q.put('hello baby')

    def consumer(q):
    print(q.get())





    if __name__ == '__main__':
    q=Queue() #生成一个队列对象
    p1=Process(target=producer,args=(q,))
    c1=Process(target=consumer,args=(q,))
    p1.start()
    c1.start()
    # print(q.get())

    生产者消费者模型****

    字面意思:
    生产者:火锅店老板
    消费者:吃火锅的人
    没有任何信息交互的情况下:火锅店老板不知道要买多少菜才能解决今日的客户需求,只能自己估算
    吃火锅的人也不知道今天火锅店有没有火锅可以吃,处于一个信息不互通的情况下
    就会造成:吃火锅的人多,但是准备的菜少
    准备的菜多,但是吃火锅的人少
    为了解决这个问题,可以提供预约服务
    程序中:
    生产者:产生数据的
    消费者:处理数据的
    解决供需不平衡的问题:
    可以将数据放在管道中,专门用来存放固定数量的数据
    解决生产者和消费者不需要直接打交道,两者都通过队列实现数据传输
    Queue:管道+锁

    from multiprocessing import Queue,Process
    import time,random
    def producer(name,food,q):
    for i in range(10):
    data=print('%s 生产%s %s'%(name,food,i))
    time.sleep(random.randint(1,3))
    print(data)
    q.put(data)
    def constumer(name,q):
    while True:
    data=q.get()
    time.sleep(random.randint(1,3))
    print('%s 吃了%s'%(name,data))

    if __name__=='__main__':
    q=Queue()
    p1=Process(target=producer,args=('egon','baozi',q))
    p2=Process(target=producer,args=('bob','rou',q))
    c1=Process(target=constumer,args=('bob',q))
    c2=Process(target=constumer,args=('bob',q))
    p1.start()
    p2.start()
    c1.start()
    c2.start()

    '''
    生产者消费者模型(爬虫)
    生产者:做包子的 生产数据的
    消费者:买包子的 处理数据的

    解决供需不平衡的问题(做包子的做多了,买包子的人多了)
    定义一个队列,用来存放固定数量的数据
    解决生产者和消费者不需直接打交道,两者都通过队列实现数据传输

    Queue:管道+锁

    from multiprocessing import Queue,Process
    import time,random
    def producer(name,food,q):
    for i in range(10):
    data='%s生产了%s%s'%(name,food,i)
    time.sleep(random.randint(1,3))
    print(data)
    q.put(data)
    def consumer(name,q):
    while True:
    data=q.get() #
    time.sleep(random.randint(1,3))
    print('%s 吃了%s '%(name,data))


    if __name__ == '__main__':
    q=Queue()
    p1=Process(target=producer,args=('egon','包子',q))
    p2=Process(target=producer,args=('tank','生蚝',q))
    c1=Process(target=consumer,args=('lll',q))
    c2=Process(target=consumer,args=('yyy',q))
    p1.start()
    p2.start()
    c1.start()
    c2.start()
    '''
    # from multiprocessing import Queue,Process,JoinableQueue
    # import time,random
    #
    # def pruducer(name,food,q):
    # for i in range(3):
    # data='%s生产了%s%s'%(name,food,i)
    # time.sleep(random.randint(1,3))
    # print(data)
    # q.put(data)
    #
    # # pass
    # def consumer(name,q):
    # while True:
    # data=q.get()
    # if data is None:break
    # time.sleep(random.randint(1,3))
    # print('%s 吃了%s'%(name,data))
    # q.task_done()#告诉你的队列,你已经将数据取并且处理完毕
    #
    # if __name__ == '__main__':
    # q=JoinableQueue()
    #
    # # # p_list=[]
    # # for i in range(2):
    # # p=Process(target=pruducer,args=('name',i,q))
    # # p.start()
    # # # p_list.append(i)
    # # for i in range(2):
    # # c=Process(target=consumer,args=('lll',i,q))
    # # c.start()
    # p1=Process(target=pruducer,args=('egon','包子',q))
    # p2=Process(target=pruducer,args=('tank','牛肉',q))
    # c1=Process(target=consumer,args=('yyy',q))
    # c2=Process(target=consumer,args=('mmm',q))
    # p1.start()
    # p2.start()
    # # c1.daemon=True
    # # c2.daemon=True
    # c1.start()
    # c2.start()
    # #等待生产者生产完所有的数据
    # p1.join()
    # p2.join()
    # #在生产者生产完数据之后往队列里面放一个提示性的消息,告诉消费者已经没有数据了,你走吧,不要等了
    # # q.put(None)
    # # q.put(None)
    # q.join()#等待队列中数据全部取出
    # print('zhu')
    import time,random
    from multiprocessing import Queue,Process,JoinableQueue


    def producer(name,food,q):
    for i in range(10):
    res='%s%s'%(food,i)
    time.sleep(random.randint(1,3)) #模拟生产者产生数据的时间

    q.put(res)
    print('厨师%s 生产了%s'%(name,res))
    # q.put(None)#放在这里会出现有的消费者还没有吃完就让滚蛋的情况,应该放在所有数据的最后

    def constumer(name,q):
    while True:
    # data=q.get() #没数据就一直在等待,处于阻塞,关键在于什么时候死
    data = q.get()
    # if data==None:break
    time.sleep(random.randint(1,3)) #模拟消费者处理数据的时间
    print('吃货%s吃了%s'%(name,data))
    q.task_done()

    if __name__ == '__main__':
    q=JoinableQueue
    # q=Queue()
    #生产者们
    p1=Process(target=producer,args=('egon','包子',q))
    p2=Process(target=producer,args=('liuxx','肉',q))
    #消费者们
    c1=Process(target=constumer,args=('json',q))
    c2=Process(target=constumer,args=('tank',q))
    c1.daemon=True
    c2.daemon=True #守护进程
    #启动进程,一共有5个
    p1.start()
    p2.start()
    c1.start()
    c2.start()
    # p1.join()
    # p2.join()
    # q.put(None)#有几个消费者就放几个none
    # q.put(None)
    p1.join()
    p2.join()#生产者全部生产完了
    q.join()#主进程等q结束,即q内的数据被取干净了
    print('主')



    线程理论

    '''
    工厂生产橡胶
    车间和流水线的关系

    1.什么是线程
    进程:资源单位(占用的是内存空间独立的)
    线程:执行单位(被CPU执行的)

    注意:每一个进程中都会自带一个线程

    2.为什么要有线程

    开一个进程:
    申请内存空间 耗时
    将代码拷贝到申请的内存空间中 耗时
    开线程:
    不需要申请内存空间
    不需要将代码拷贝到申请的内存空间

    开线程的开销远远小于开进程的开销!!!

    3.如何使用线程


    '''


    工厂生产橡胶
    一个车间和里面的机器
    车间:存放机器的,如果需要多个任务同时开始,就放多个机器
    机器:生产具体的产品,需要资源就找车间要
    什么是线程?
    进程:资源单位(占用的是内存空间,彼此之间是独立的)
    线程:执行单位(直接被CPU执行的)
    注意:每一个进程都自带一个线程

    创建线程的两种方式
    1.自己定义一个函数,调用Thread传参(target=’自己写的函数名‘,args=(v1,))
    2.写一个类,继承Thread,在里面固定写一个run方法
    注意:线程开启速度非常快,几乎代码执行完毕线程就会开启
    所以会出现先打印子线程在打印主线程

    '''
    from threading import Thread
    import time

    def task(name):
    print('%s is running'%name)
    time.sleep(2)
    print('%s is ending'%name)

    if __name__ == '__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(2)
    print('%s is ending'%self.name)

    if __name__ == '__main__':
    t=Mythread('json')
    t.start() #开启线程的速度超级快,几乎代码执行完毕线程就会开启
    print('主')


    join方法
    让主线程等待子线程程序运行结束,不会影响子线程的执行过程!
    会将并发变成串行

    线程对象的其他属性和方法
    active_count() #查看当前正在活跃的线程数
    current_thread().name#查看线程和子线程
    os.getpid()#查看线程id
                   守护线程

    from threading import Thread
    import time,random

    def task(name):

    print('%s is running'%name)
    time.sleep(2)
    print('%s is over'%name)

    if __name__ == '__main__':
    t=Thread(target=task,args=('aaa',))
    t.daemon=True
    t.start()
    print('主')


    主线程要等待所有非守护线程的结束才可以结束
    线程间数据是否隔离?
    数据共享


    from threading import Thread
    x=10

    def task():
    global x
    x=666


    t=Thread(target=task)

    t.start()
    t.join()
    print(x)


    线程互斥锁

    from threading import Thread,Lock

    import time

    mutex=Lock()
    n=100

    def task():
    global n
    mutex.acquire()
    temp=n
    time.sleep(0.1) #模拟网络延迟

    n=temp-1
    mutex.release()

    l_list=[]
    for i in range(100):
    t=Thread(target=task)
    t.start()
    l_list.append(t)

    for t in l_list:
    t.join()

    print(n) #0


    将并发变成串行

  • 相关阅读:
    WindowsForm:百科
    App-应用程式:百科
    ASP.NET:目录
    ASP.NET:百科
    操作平台:.NET
    DB-触发器:百科
    DB-DatabaseLink:百科
    5090 众数
    计数排序
    归并排序
  • 原文地址:https://www.cnblogs.com/mcc61/p/10834720.html
Copyright © 2011-2022 走看看