• 饮冰三年-人工智能-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

  • 相关阅读:
    CCF CSP 201503-1 图像旋转
    CCF CSP 201403-1 相反数
    CCF CSP 201312-1 出现次数最多的数
    CCF CSP 201703-3 Markdown
    CCF CSP 201709-3 JSON查询
    CCF CSP 201709-2 公共钥匙盒
    CCF CSP 201709-1 打酱油
    CCF CSP 201604-4 游戏
    CCF CSP 201604-1 折点计数
    CCF CSP 201612-1 中间数
  • 原文地址:https://www.cnblogs.com/YK2012/p/10011371.html
Copyright © 2020-2023  润新知