饮冰三年-人工智能-Python-20 Python线程、进程、线程

进程:最小的数据单元

线程:最小的执行单元

一:

1:线程1

import threading #线程
import time
def Music():
    print("Listen Music Begin %s" %time.ctime())
    time.sleep(3)
    print("Listen Music End %s" %time.ctime())
def Game():
    print("Play Game Begin %s" %time.ctime())
    time.sleep(5)
    print("Play Game End %s" %time.ctime())
if __name__ == '__main__':
    t1 = threading.Thread(target=Music)
    t1.start()
    t2 = threading.Thread(target=Game)
    t2.start()

    print("ending......")
实例1

import threading #线程
import time
def Music():
    print("Listen Music Begin %s" %time.ctime())
    time.sleep(3)
    print("Listen Music End %s" %time.ctime())
def Game():
    print("Play Game Begin %s" %time.ctime())
    time.sleep(5)
    print("Play Game End %s" %time.ctime())
if __name__ == '__main__':
    t1 = threading.Thread(target=Music)
    t1.start()
    t2 = threading.Thread(target=Game)
    t2.start()
    t1.join()
    t2.join()
    print("ending......")
线程join

import threading #线程
import time
def Music(musicName):
    print("Listen Music【%s】 Begin %s" %(musicName,time.ctime()))
    time.sleep(3)
    print("Listen Music【%s】 End %s" %(musicName,time.ctime()))
def Game(playName):
    print("Play Game【%s】 Begin %s" %(playName,time.ctime()))
    time.sleep(5)
    print("Play Game【%s】 End %s" %(playName,time.ctime()))
if __name__ == '__main__':
    t1 = threading.Thread(target=Music,args=("My Heart Will Go On",))
    t2 = threading.Thread(target=Game,args=("植物大战僵尸",))
    threads=[]
    threads.append(t1)
    threads.append(t2)
    for t in threads:
        t.start();
    print("ending......")
线程参数

import threading #线程
import time
def Music(musicName):
    print("Listen Music【%s】 Begin %s" %(musicName,time.ctime()))
    time.sleep(3)
    print("Listen Music【%s】 End %s" %(musicName,time.ctime()))
def Game(playName):
    print("Play Game【%s】 Begin %s" %(playName,time.ctime()))
    time.sleep(5)
    print("Play Game【%s】 End %s" %(playName,time.ctime()))
t1 = threading.Thread(target=Music,args=("My Heart Will Go On",))
t2 = threading.Thread(target=Game,args=("植物大战僵尸",))
threads=[]
threads.append(t1)
threads.append(t2)
if __name__ == '__main__':
    t2.setDaemon(True)
    for t in threads:
        t.start();
    print("ending......")
守护线程

# 多线程为什么要使用锁?
# 多线程共用一个数据集,不使用可能会造成数据不准确
#1:引入多线程模块
import threading
import time
# 2:定义一个变量(数据集)
num=100
# 3:定义一个方法,操作全局变量
def sub():
    global num
    temp = num
    time.sleep(0.001)
    num=temp-1
# 4:创建多个线程
ts=[]
for i in range(0,100):
    t=threading.Thread(target=sub)
    t.start()
    ts.append(t)
for t in  ts:
    t.join()
print(num)
未加锁,数据结果有误

# 多线程为什么要使用锁?
# 多线程共用一个数据集,不使用可能会造成数据不准确
#1:引入多线程模块
import threading
import time
# 2:定义一个变量(数据集)
num=100
# 3:定义一个方法,操作全局变量
# 5:创建锁
lock=threading.Lock()
def sub():
    global num
    # 5.1 加锁
    lock.acquire()
    temp = num
    time.sleep(0.001)
    num=temp-1
    # 5.2 释放锁
    lock.release()
# 4:创建多个线程
ts=[]
for i in range(0,100):
    t=threading.Thread(target=sub)
    t.start()
    ts.append(t)
for t in  ts:
    t.join()

print(num)
同步锁

#当两个锁之间出现递归调用,彼此之间相互等待,就会出现死锁
#线程的另一种实现方式(通过自定义类)
#1:引入threading、time
import threading
import time
# 定义两个锁
lockA=threading.Lock()
lockB=threading.Lock()
#3:定义一个线程(线程中存在两个方法,存在递归调用)
class MyThread(threading.Thread):
    #定义两个方法
    def actionA(self):
        # 获取A锁
        lockA.acquire()
        print(self.name,"gotA",time.ctime())
        time.sleep(1)
        #然后再获取B锁
        lockB.acquire()
        print(self.name,"gotB",time.ctime())
        time.sleep(2)
        # 先释放B锁,
        lockB.release()
        # 后释放A锁
        lockA.release()
    def actionB(self):
        # 获取B锁
        lockB.acquire()
        print(self.name, "gotB", time.ctime())
        time.sleep(1)
        # 然后再获取A锁
        lockA.acquire()
        print(self.name, "gotA", time.ctime())
        time.sleep(2)
        # 先释放A锁,
        lockA.release()
        # 后释放B锁
        lockB.release()
    #实现run方法
    def run(self):
        self.actionA()
        self.actionB()

# 4:创建多个线程
for i in range(0,5):
    t=MyThread()
    t.start()
死锁现象

#当两个锁之间出现递归调用,彼此之间相互等待,就会出现死锁
#线程的另一种实现方式(通过自定义类)
#1:引入threading、time
import threading
import time
# 定义两个锁
lockA=threading.Lock()
lockB=threading.Lock()

lockR=threading.RLock() #把两个锁替换成一个RLock,内部通过计数器实现
#3:定义一个线程(线程中存在两个方法,存在递归调用)
class MyThread(threading.Thread):
    #定义两个方法
    def actionA(self):
        # 获取A锁
        # lockA.acquire()
        lockR.acquire()
        print(self.name,"gotA",time.ctime())
        time.sleep(1)
        #然后再获取B锁
        # lockB.acquire()
        lockR.acquire()
        print(self.name,"gotB",time.ctime())
        time.sleep(2)
        # 先释放B锁,
        # lockB.release()
        lockR.release()
        # 后释放A锁
        # lockA.release()
        lockR.release()
    def actionB(self):
        # 获取B锁
        # lockB.acquire()
        lockR.acquire()
        print(self.name, "gotB", time.ctime())
        time.sleep(1)
        # 然后再获取A锁
        # lockA.acquire()
        lockR.acquire()
        print(self.name, "gotA", time.ctime())
        time.sleep(2)
        # 先释放A锁,
        # lockA.release()
        lockR.release()
        # 后释放B锁
        lockR.release()
        # lockB.release()
    #实现run方法
    def run(self):
        self.actionA()
        self.actionB()

# 4:创建多个线程
for i in range(0,5):
    t=MyThread()
    t.start()
递归锁,解决死锁

# 1:引入包
import threading
import time
# 2:创建同步锁
event = threading.Event()
#3:创建线程对象
class Boss(threading.Thread):
    def run(self):
        print("大家加班")
        event.set()
        time.sleep(5)
        print("下班了")
        event.set()
class Worker(threading.Thread):
    def run(self):
        event.wait()
        print("不加班,不加班")
        time.sleep(1)
        event.clear()
        event.wait()
        print("Oh Yeah")
# 4:创建线程对象,并放入到线程集合中
ts=[]
t=Boss()
ts.append(t)
for i in range(0,5):
    ts.append(Worker())
for t in ts:
    t.start()
同步锁

# 信号量类似于停车场,一次只能处理n个线程
# 1:导包
import threading,time
# 2:设置信号量
semaphore = threading.Semaphore(5)
# 3:创建线程对象
class MyThread(threading.Thread):
    def run(self):
        if semaphore.acquire():
           print(self.name)
           time.sleep(3)
           semaphore.release()

# 4:创建线程对象
for i in range(0,20):
    t=MyThread()
    t.start()
信号量

# 队列:多线程,线程安全
# 1:引包
import queue,time
# 2:创建对象
q=queue.Queue(3)  #3表示队列的总容量为3、默认为先进先出类型
# 3:常用的方法
q.put("#3333")          #添加数据
q.put({"ab":"cd"})

print(q.get())          #获取数据
print(q.qsize())         #获取队列的长度
print(q.empty())        #判断是否为空
print(q.full())         #判断是否已满
print(q.task_done())    #每对队列进行一次操作以后就会返回True
print(q.join())         #task_done 对应的就是join
队列的常见属性
# 通过队列,设置一个生产者消费者的开发模型
# 1:引包
import threading,queue,time,random
# 2:定义队列
que=queue.Queue()
# 3:定义两个生产者、消费者的类
def Producer(name):
    countBaoZi=1;
    while countBaoZi <= 10:
        # print("包子数量小于10,开始生产包子")
        time.sleep(random.randrange(1,3))
        que.put(countBaoZi)
        print("生产者:%s,生产了【包子%s】" % (name, countBaoZi))
        countBaoZi = countBaoZi + 1
def Consumer(name):
    countBaoZi=1
    while countBaoZi<=10:
        time.sleep(random.randrange(1,4))
        if que.empty():
            print("老板没包子了")
        else:
            print("现在还有%s个包子" % que.qsize())
            curBaoZi = que.get()
            print("消费者:%s,吃了包子【%s】" % (name, curBaoZi))

# 4:创建多个线程
producerA = threading.Thread(target=Producer,args=("A大厨",))
consumerA = threading.Thread(target=Consumer,args=("A君",))
consumerB = threading.Thread(target=Consumer,args=("B君",))

producerA.start()
consumerA.start()
consumerB.start()
队列-线程 生产者、消费者模式

# 通过队列,设置一个生产者消费者的开发模型
# 升级版,包子吃了以后,还需要再去检查一下,有没有包子if que.empty() 这样浪费时间,
# 应该是:吃完就告诉老板直接生产,生产好了再通知客户去吃
# 1:引包
import threading,queue,time,random
# 2:定义队列
que=queue.Queue()
# 3:定义两个生产者、消费者的类
def Producer(name):
    countBaoZi=1;
    while countBaoZi <= 10:
        time.sleep(random.randrange(1,3))
        que.put(countBaoZi)
        print("生产者:%s,生产了【包子%s】" % (name, countBaoZi))
        countBaoZi = countBaoZi + 1
        que.join()

def Consumer(name):
    countBaoZi=1
    while countBaoZi<=10:
        time.sleep(random.randrange(1,4))
        print("现在还有%s个包子" % que.qsize())
        curBaoZi = que.get()
        time.sleep(1)
        print("消费者:%s,吃了包子【%s】" % (name, curBaoZi))
        que.task_done()

# 4:创建多个线程
producerA = threading.Thread(target=Producer,args=("A大厨",))
consumerA = threading.Thread(target=Consumer,args=("A君",))
consumerB = threading.Thread(target=Consumer,args=("B君",))

producerA.start()
consumerA.start()
consumerB.start()
队列-线程 生产消费2

二 进程

# 1:导包
import time
from multiprocessing import Process
# 2:创建进程对象集合
pros=[]
# 3:定义方法
def music(musicName):
    print("开始播放:%s.%s" %(musicName,time.ctime()))
    time.sleep(2)
    print("播放结束:%s.%s" %(musicName,time.ctime()))
def play(gameName):
    print("开始打:%s.%s" %(gameName,time.ctime()))
    time.sleep(5)
    print("游戏结束:%s.%s" %(gameName,time.ctime()))
if __name__ == '__main__':
    # 4:创建进行对象
    mu=Process(target=music,args=("My Heart Will Go On",))
    mu.start()
    mg=Process(target=play,args=("植物大战僵尸",))
    mg.start()
进程

# 1:导包
import time
from multiprocessing import Process
# 2:创建进程对象集合
pros=[]
# 3:定义方法
def music(musicName):
    print("开始播放:%s.%s" %(musicName,time.ctime()))
    time.sleep(2)
    print("播放结束:%s.%s" %(musicName,time.ctime()))
def play(gameName):
    print("开始打:%s.%s" %(gameName,time.ctime()))
    time.sleep(5)
    print("游戏结束:%s.%s" %(gameName,time.ctime()))
if __name__ == '__main__':
    # 4:创建进行对象
    mu=Process(target=music,args=("My Heart Will Go On",))
    # 4.2:进程常用的属性和方法
    #mu.join() #进程阻塞
    mu.start() #开启进程
    time.sleep(1)
    mu.terminate() #结束进程
    print(" 进程名称 %s, 进程编码 %s,"%(mu.name,mu.pid))
常用的属性和方法

 进程之间的三种通讯方法

进程队列

# 1:导包
from multiprocessing import Process,Queue
import time
#2:定义一个方法,用于向队列中赋值
def putAction(q,n):
    q.put(n*(n+1))
    print("当前队列的id:",id(q))

if __name__ == '__main__':
    # 3:创建一个队列
    que=Queue()
    print("main方法中队列的id:", id(que))
    # 4:通过循环创建多个进程
    for i in range(0,3):
        p=Process(target=putAction,args=(que,i,))
        p.start()
    print(que.get())
    print(que.get())
    print(que.get())
通过进程队列实现数据通信

# 管道相当于生成两个连接对象,一个主进程使用,另外一个传递给子进程使用
# 1:导包
from multiprocessing import Process,Pipe
import time
# 2:定义函数
def ConnAction(conn):
    # 获取传递过来的conn连接对象
    print("准备发送消息,时间%s"%(time.ctime()))
    conn.send("土豆土豆,我是地瓜,收到请回答")
    time.sleep(2)
    print("准备接收消息,时间%s"%(time.ctime()))
    responInfo = conn.recv()
    print(responInfo,time.ctime())

if __name__ == '__main__':
    # 创建管道对象
    par_conn,child_conn=Pipe()
    # 创建进程
    p=Process(target=ConnAction,args=(child_conn,))
    p.start()
    print("主进程,准备接收消息,%s"%(time.ctime()))
    respons=par_conn.recv()
    print(respons,time.ctime())
    time.sleep(2)
    print("主进程,准备发送消息,%s"%(time.ctime()))
    par_conn.send("地瓜地瓜,我是土豆");
通过管道实现数据通信

# 1:导包
from multiprocessing import Process,Manager
#2:定义方法
def manaAction(d,l,n):
    # 对字典进行操作
    d[n]="1"
    d["2"]=2
    # 对列表进行操作
    l.append(n)
if __name__ == '__main__':
    # 创建Manager对象中的数据类型
    with Manager() as  manager:
        d=manager.dict()
        l=manager.list(range(5))
        p_list=[]
        # 创建进程
        for i in range(0,5):
            p=Process(target=manaAction,args=(d,l,i))
            p.start()
            p_list.append(p)
        for res in p_list:
            res.join()
        print(d)
        print(l)
通过Manager实现数据通信

# 1:导入包
from multiprocessing import Process,Lock
import time
#定义方法
def printPro(l,n):
    with l:
        print("Hello,World %s,%s"%(n,time.ctime()))
        time.sleep(1)

if __name__ == '__main__':
    l=Lock()
    for i in range(0, 5):
        p = Process(target=printPro, args=(l,i,))
        p.start()
进程锁

# 1:导包
from multiprocessing import Process,Pool
import time

# 3:创建方法
def foo(i):
    time.sleep(1)
    print(i)
    return i
# 4:创建回调方法
def bar(arg):
    #回调方法在主函数中执行
    print("hello,%s"%arg)

if __name__ == '__main__':
    # 2:创建进程池对象
    pool = Pool(5)
    for i in range(0,30):
        pool.apply_async(func=foo,args=(i,),callback=bar)
    pool.close()
    pool.join()
进程池

 三 协程

  协程是一种非抢占式程序,其本质是一个线程。

  优点:1:灭有切换消耗;2:没有锁的概念

  缺点:无法使用多核,但是可以通过多进程+协程弥补

# 通过yield来实现
# 1:导包
import time
#2:消费者
def Consumer(name):
    print("准备开始吃包子")
    while True:
        newbaozi=yield
        print("%s吃了包子%s"%(name,newbaozi))
#3:生产者
def Product():
    r=con.__next__()
    r2=con2.__next__()
    baoziName=1
    while True:
        time.sleep(1)
        print("生产者,生产了%s和%s包子"%(baoziName,baoziName+1))
        con.send(baoziName)
        con2.send(baoziName+1)
        baoziName+=2
#主方法
if __name__ == '__main__':
    #创建两个用户
    con=Consumer("张三")
    con2=Consumer("李四")
    Product()
协程-yield

from greenlet import greenlet
def test1():
    print(12)
    gr2.switch()
    print(34)
    gr2.switch()
def test2():
    print(56)
    gr1.switch()
    print(78)
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
协程-greenlet

# 1:导包
import gevent
import requests,time

# 记录开始时间
start = time.time()
def f(url):
    # print("Get:%s" %url)
    reap=requests.get(url)
    data=reap.text
    print("%s网址上一共有%s字节"%(url,len(data)))
gevent.joinall([
        gevent.spawn(f, 'https://www.python.org/'),
        gevent.spawn(f, 'https://www.yahoo.com/'),
        gevent.spawn(f, 'https://www.baidu.com/'),
        gevent.spawn(f, 'https://www.sina.com.cn/'),
])
print("耗时",time.time()-start)
f('https://www.python.org/')
f('https://www.yahoo.com/')
f('https://www.baidu.com/')
f('https://www.sina.com.cn/')
print("耗时",time.time()-start)
协程-gevent

 

posted @ 2018-11-24 17:11  逍遥小天狼  阅读(215)  评论(0编辑  收藏  举报