Python入门学习-DAY35-线程

一、进程补充

1.进程间通信(IPC机制)

进程间通讯有两种方法:管道或者队列。

1 队列和管道都是将数据存放于内存中

2 队列又是基于(管道+锁)实现的,可以让我们从复杂的锁问题中解脱出来。

        

from multiprocessing import Queue

q=Queue(3)#3是队列允许存在的个数
q.put('1')
q.put('2')
q.put('3')



print(q.get(block=True,timeout=2))
print(q.get())
print(q.get())

block默认是True,意思是可以阻塞。timeout是阻塞时间,阻塞时间到了会报错

那么什么情况下会阻塞:

1.当限制队列里的数量时,放入超过限制的消息,会阻塞,等待第一个放入的被取走,才会继续执行

2.当限制队列里的数量时,取出超过限制的消息,因为此时的队列是空的,只有队列里再次放入内容时才会继续执行

 

2.生产者消费者模型

1. 什么是生产者消费者模型

  生产者:代指生产数据的任务
  消费者:代指处理数据的任务
  该模型的工作方式:
    生产生产数据传递消费者处理

  实现方式:
    生产者---->队列<------消费者

2. 为何要用

当程序中出现明细的两类任务,一类负责生产数据,一类负责处理数据
就可以引入生产者消费者模型来实现生产者与消费者的解耦合,平衡生产能力与消费能力,从提升效率

3. 如何用

from multiprocessing import  Process,Queue
import time,random

def producer(name,food,p):
    for i in range(3):
        res='%s%s'%(food,i)
        time.sleep(random.randint(1,3))
        print('%s生产了%s'%(name,res))
        p.put(res)

def customer(name,p):
    while True:
        res=p.get()
        if res is None:break#判断消费者是否消费完,如果消费完,就会取到NONE
        time.sleep(random.randint(1,3))
        print('%s吃了%s'%(name,res))

if __name__ == '__main__':
    p=Queue()
    p1=Process(target=producer,args=('1','葱油拌屎',p,))
    p2 = Process(target=producer, args=('2', '手抓屎', p,))
    p3 = Process(target=producer, args=('3', '飘香拌屎', p,))
    c1=Process(target=customer,args=('姚晓锋',p,))
    c2 = Process(target=customer, args=('阿飞', p,))
    p1.start()
    p2.start()
    p3.start()

    c1.start()
    c2.start()

    p1.join()
    p2.join()
    p3.join()#说明此时生产者已经生产完了
    p.put(None)#有几个消费者就加上几个NONE
    p.put(None)
    c1.join()
    c2.join()
    print('')
方式一
from multiprocessing import  Process,JoinableQueue
import time,random

def producer(name,food,p):
    for i in range(3):
        res='%s%s'%(food,i)
        time.sleep(random.randint(1,3))
        print('%s生产了%s'%(name,res))
        p.put(res)

def customer(name,p):
    while True:
        res=p.get()
        time.sleep(random.randint(1,3))
        print('%s吃了%s'%(name,res))

if __name__ == '__main__':
    p=JoinableQueue()
    p1=Process(target=producer,args=('1','葱油拌屎',p,))
    p2 = Process(target=producer, args=('2', '手抓屎', p,))
    p3 = Process(target=producer, args=('3', '飘香拌屎', p,))
    c1=Process(target=customer,args=('姚晓锋',p,))
    c2 = Process(target=customer, args=('阿飞', p,))
    c1.daemon=True
    c2.daemon=True
    p1.start()
    p2.start()
    p3.start()

    c1.start()
    c2.start()

    p1.join()
    p2.join()
    p3.join()
    p.join()#主进程等待队列里为空
    #一旦队列为空,说明消费者取完了队列,消费者没有价值了
    print('')
方式二

 

 

二、线程理论

1 什么是线程

进程其实一个资源单位,而进程内的线程才是cpu上的执行单位
线程其实指的就是代码的执行过程

2 为何要用线程

线程的优点
1. 同一进程下的多个线程共享该进程内的资源
2. 创建线程的开销要远远小于进程

 

三、开启线程的两种方式

线程开启的方式与进程一致

from threading import Thread
import time


def task(name):
    print('%s is running'%name)
    time.sleep(3)
    print('%s is done'%name)


if __name__ == '__main__':
    p=Thread(target=task,args=('yxf',))
    p.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 done'%self.name)


if __name__ == '__main__':
    p=Mythread('egon')
    p.start()
    print('')
方式二

四、线程特性介绍

Thread实例对象的方法

 

  isAlive(): 返回线程是否活动的。

  getName(): 返回线程名。

  setName(): 设置线程名。

threading模块提供的一些方法

 

  threading.currentThread(): 返回当前的线程变量。

  threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 

  threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果

同一进程下的线程共享资源

from threading import Thread,current_thread,active_count


n=100
def task():
    global n
    n=0
    print('子进程n=',n,current_thread())



if __name__ == '__main__':
    p1=Thread(target=task,)
    p1.start()
    print(active_count())
    p1.join()
    print(active_count())
    print('主进程n=',n,current_thread())
代码验证

 

五、守护线程

守护线程的生命周期取决于被守护线程(主线程)的生命周期,但是主线程要等到非守护线程都结束执行才会执行完毕

也就是说,只有非守护线程都执行完毕,守护线程才会结束

from threading import Thread
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-------")
代码验证

 

 

 

 

六、线程互斥锁

与进程一致

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()

if __name__ == '__main__':
    t_l=[]
    for i in range(100):
        t=Thread(target=task)
        t_l.append(t)
        t.start()

    for t in t_l:
        t.join()
    print(n)
代码验证

 

posted @ 2018-09-06 17:02  藏岚  阅读(174)  评论(0编辑  收藏  举报