线程

进程间通信

IPC机制
进程之间存在内存的物理隔离,数据不共享,所以需要有能存放公共数据的地方
1.管道
   import subprocess
   subprocess.Popen('dir',
                   shell=True,
                   stdout=subprocess.PIPE, #把数据存入管道中
                   stderr=subprocess.PIPE)
   2.队列 (等于管道+锁)
   from multiprocessing import Queue
  q=Queue(3)#创建队列对象,并且只能存放3个数据
       q.put(obj) #往队列中添加数据
       q.put(obj)
       q.put_nowait(obj)#添加数据,无等待,满了直接报错,这里没有满,不会报错,其实就等同于q.put(block=False)
       print(q.full()) #如果已经满的话,输出True,否则为False
       q.put(obj,block=True,timeout=1)#等待一秒,如果数据仍然是满的,没有被取出,就直接报错(没有timeout默认一直等待)
       
       q.get()#在队列中取数据
       q.get()
       q.get_nowait()#无等待取出数据,没有数据直接报错empty,等同于q.get(block=False)
       print(q.empty())#如果已经空的话,输出True,否则为False
        q.get(obj,block=True,timeout=1)#等待一秒,如果数据仍然是空的,就直接报错(没有timeout默认一直等待)

生产者消费者模型

解决供需不平衡的问题
定义一个队列,用来存放固定数量的数据
   让一个生产者和消费者不直接打交道,解耦合
1.例子(在生产者运行结束后,队列添加None,当取到None的时候结束等待终止循环,让主进程正常结束)
from multiprocessing import Process,Queue
import time
import random
   
def producer(name,food,q):
for i in range(5):
       data='%s%s'%(food,i)
       time.sleep(random.randint(1,3))#模拟制作时间,1到3秒不等
       print('%s制作了%s'%(name,data))
       q.put(data)
       
def customer(name,q):
while 1:
       mes=q.get() #如果没有收到数据,会一直等待,所以才有下面的if
       if mes==None:break #当收到None的时候,停止循环,让主进程正常退出
       time.sleep(random.randint(1,3))#模拟进食时间
       print('%s吃了%s'%(name,mes))
       
if __name__=='__main__':
   q=Queue() #生成一个队列对象,用来给消费者和生产者搭桥
   p=Process(target=producer,args=('大厨','牛排',q))#生成一个生产者进程
   c=Process(target=customer,args=('我',q))#生成一个消费进程
   p.start()
   c.start()
   p.join()#确保在生产者结束
   q.put(None)#确保在生产者结束后,给列表添加None

2.方法二(利用守护进程,确保生产者结束后,列表中没有数据的时候,消费者进程随着主进程结束而结束)
from multiprocessing import Process,JoinableQueue
import time
import random
   
def producer(name,food,q):
for i in range(5):
       data='%s%s'%(food,i)
       time.sleep(random.randint(1,3))#模拟制作时间,1到3秒不等
       print('%s制作了%s'%(name,data))
       q.put(data)
       
def customer(name,q):
while 1:
       mes=q.get()
       time.sleep(random.randint(1,3))#模拟进食时间
       print('%s吃了%s'%(name,mes))
       q.task_done()#告诉队列数据已经取出,且已经处理完毕
       
if __name__=='__main__':
   q=JoinableQueue() #生成一个队列对象,用来给消费者和生产者搭桥
   p=Process(target=producer,args=('大厨','牛排',q))#生成一个生产者进程
   c=Process(target=customer,args=('我',q))#生成一个消费进程
   c.daemon=True   #把消费者做成守卫进程,随着主进程一起结束
   p.start()
   c.start()
   p.join()#确保在生产者结束
   q.join()#确保数据已经全部取出

线程理论

进程:资源单位
线程:执行单位(执行的最小单位)
每一个进程中都会自带一个线程

为什么要有线程
开一个进程
  申请内存空间 耗时
       将代码拷贝到申请的内存空间中  耗时
开线程
  不需要申请内存空间
    开线程的消耗远远小于开进程的开销!!(时间约100倍)

开线程的两种方式

方式一
from threading import Thread
import time

def task(name):
   print('%s is running'%name)
   time.sleep(1)
   print('%s is over'%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(1)
       print('%s is over'%self.name)

if __name__ == '__main__':
   t = MyThread('jason')
   t.start()
   print('主')

线程之间数据共享的

from threading import Thread

x = 100

def task():
   global x
   x = 666

t = Thread(target=task)
t.start()
t.join()#确保子进程先运行
print(x)
#输出为666,说明资源是共享的,MAYBE='其实就是访问全局的变量,子线程中(局部)可以访问主线程(全局),但是主线程不能访问子线程'?

线程互斥锁

from threading import Thread,Lock
import time
import random

mutex = Lock()
n = 100

def task():
   global n
   mutex.acquire()
   tmp = n
   time.sleep(0.1)
   n = tmp -1
   mutex.release()


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

for t in t_list:
   t.join()

print(n)

线程对象的其他属性和方法

from threading import Thread,active_count,current_thread
import os
import time


def task(name):
   # print('%s is running'%name,os.getpid())
   print('%s is running'%name,current_thread().name,current_thread().getName())
   time.sleep(1)
   print('%s is over'%name)

def info(name):
   print('%s is running' % name, current_thread().name, current_thread().getName())
   time.sleep(1)
   print('%s is over' % name)

t = Thread(target=task,args=('关磊',),name='线程')
t1 = Thread(target=info,args=('关超',))
t.start()
t1.start()
t.join()
print(active_count())  # 当前存活的线程数
print(os.getpid())  #得到pid,进程的pid,同一进程中都相同
print(current_thread().name)
print(current_thread().getName()) #得到线程名字,没有采用默认

守护线程

from threading import Thread
import time


def task(name):
   print('%s is running'%name)
   time.sleep(1)
   print('%s is over'%name)

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

 

 

posted @ 2019-05-07 22:08  Mr-Bear  阅读(374)  评论(0编辑  收藏  举报