• python的threading的使用(join方法,多线程,锁threading.Lock和threading.Condition


    一、开启多线程方法一

    import threading,time
    
    def write1():
        for i in range(1,5):
            print('1')
            time.sleep(1)
    
    
    def write12():
        for i in range(1, 5):
            print('2')
            time.sleep(1)
    
    # 给两个函数开一个线程,target后面赋值函数名
    t1 = threading.Thread(target=write1)
    t2 = threading.Thread(target=write12)
    # 使用start函数启动这个线程
    t1.start()
    t2.start()
    # 输出线程数量
    print(threading.enumerate())
    '''
    输出:
    1
    2
    [<_MainThread(MainThread, started 21440)>, <Thread(Thread-1, started 2344)>, <Thread(Thread-2, started 3016)>]
    1
    2
    2
    1
    2
    1
    '''

    二、开启多线程方法二

    import threading,time
    
    class Write1Threaq(threading.Thread):
        def run(self):
            for i in range(1, 5):
                print('1----%s',threading.current_thread())
                time.sleep(1)
    
    class Write2Threaq(threading.Thread):
        def run(self):
            for i in range(1, 5):
                # 输出当前线程的名称
                print('2----%s',threading.current_thread())
                time.sleep(1)
    
    def main():
        # 继承自threading.Thread之后,只需要实现run方法,执行start函数后,会自动执行run函数
        t1 = Write1Threaq()
        t2 = Write2Threaq()
        t1.start()
        t2.start()
    
    
    if __name__ == '__main__':
        main()
    
    '''
    输出:
    1----%s <Write1Threaq(Thread-1, started 6304)>
    2----%s <Write2Threaq(Thread-2, started 10524)>
    2----%s <Write2Threaq(Thread-2, started 10524)>
    1----%s <Write1Threaq(Thread-1, started 6304)>
    2----%s <Write2Threaq(Thread-2, started 10524)>
    1----%s <Write1Threaq(Thread-1, started 6304)>
    1----%s2----%s  <Write2Threaq(Thread-2, started 10524)>
    <Write1Threaq(Thread-1, started 6304)>
    
    '''

    三、不上锁会出现的错误情况

    import time,threading
    
    value = 0
    def write():
        global value
        for i in range(1,1000000):
            value+=1
        print(value)
    
    def main():
        for i in range(1,3):
            t1 = threading.Thread(target=write)
            t1.start()
    
    if __name__ == '__main__':
        main()
    
    '''
    输出:
    # 输出结果显然不符合我们的预期,例如value等于10的时候,两个线程同时进行了两次value+1,但是这个时候两个value+1的
    # value都是10,那么结果value就是11,可以说少加了一次1
    1143699
    1227119
    '''

    四、使用Lock进行上锁解决三的问题

    import time,threading
    # 使用多线程锁
    glock = threading.Lock()
    
    value = 0
    def write():
        global value
        # 上锁
        glock.acquire()
        for i in range(1,1000000):
            value+=1
        # 解锁
        glock.release()
        print(value)
    
    def main():
        for i in range(1,3):
            t1 = threading.Thread(target=write)
            t1.start()
    
    if __name__ == '__main__':
        main()
    
    '''
    输出:这样就没问题了
    999999
    1999998
    '''

    五、condition的使用

    threading.Condition 是一个继承自threading.Lock的一个类,所以它也有上锁解锁的功能,上锁acquire,解锁ralease
    同时它还具有wait()函数,其功能为将程序在此处阻塞,可以通过函数notify,或者notify_all来进行唤醒,这两个函数要在release之前调用
    notify执行一次只会唤醒一个线程,默认是第一个等待的线程
    notify_all执行一次会唤醒所有的线程,
    import random,threading,time

    gcondition = threading.Condition()
    Money = 0
    def Create():
    global Money
    num=0
    while 1:
    if num>10:
    break
    gcondition.acquire()
    Money += random.randint(1,100)
    print('生产Money:',Money)
    gcondition.notify_all()
    gcondition.release()
    num+=1
    time.sleep(1)

    def Consumer(money):
    global Money
    num = 0
    while 1:
    if num>2:
    break
    gcondition.acquire()
    while Money<money:
    print('金额不足!')
    time.sleep(1)
    gcondition.wait()
    Money-=money
    print('总钱数:%s,花费:%s,剩余:%s。',Money+money,money,Money)
    gcondition.release()
    num+=1
    time.sleep(1)


    def main():
    for i in range(1, 3):
    t1 = threading.Thread(target=Create)
    t1.start()
    print('---------------------')
    for i in range(1, 3):
    ans = random.randint(1, 100)
    t1 = threading.Thread(target=Consumer,args=[ans])# 注意这里的参数传递方式
    t1.start()




    if __name__ == '__main__':
    main()
    '''
    生产Money: 18
    生产Money: 90
    ---------------------
    总钱数:%s,花费:%s,剩余:%s。 90 84 6
    金额不足!
    生产Money: 75
    生产Money: 105
    总钱数:%s,花费:%s,剩余:%s。 105 84 21
    金额不足!
    生产Money: 107
    生产Money: 171
    总钱数:%s,花费:%s,剩余:%s。 171 84 87
    总钱数:%s,花费:%s,剩余:%s。 87 26 61
    生产Money: 146
    总钱数:%s,花费:%s,剩余:%s。 146 26 120
    生产Money: 181
    生产Money: 230
    生产Money: 253
    总钱数:%s,花费:%s,剩余:%s。 253 26 227
    生产Money: 275
    生产Money: 320
    生产Money: 350
    生产Money: 423
    生产Money: 431
    生产Money: 484
    生产Money: 527
    生产Money: 596
    生产Money: 646
    生产Money: 721
    生产Money: 788
    生产Money: 850
    '''

    Thread参数传递的问题

     错误的参数传递

    threading.Thread(target=Consumer(ans))
    import random,threading,time
    
    gcondition = threading.Condition()
    Money = 100
    def Create():
        global Money
        num=0
        while 1:
            if num>10:
                break
            gcondition.acquire()
            Money += random.randint(1,100)
            print('生产Money:',Money)
            gcondition.notify_all()
            gcondition.release()
            num+=1
            time.sleep(1)
    
    def Consumer(money):
        global Money
        num = 0
        while 1:
            if num>2:
                break
            gcondition.acquire()
            while Money<money:
                print('金额不足!')
                time.sleep(1)
                gcondition.wait()
            Money-=money
            print('总钱数:%s,花费:%s,剩余:%s。',Money+money,money,Money)
            gcondition.release()
            num+=1
            time.sleep(1)
    
    
    def main():
        for i in range(1, 3):
            print('222')
            ans = random.randint(1, 100)
            t1 = threading.Thread(target=Consumer(ans))
            t1.start()
        print('---------------------')
    
        for i in range(1, 3):
            t1 = threading.Thread(target=Create)
            t1.start()
    
    
    
    if __name__ == '__main__':
        main()
    
    '''
    222
    总钱数:%s,花费:%s,剩余:%s。 100 12 88
    总钱数:%s,花费:%s,剩余:%s。 88 12 76
    总钱数:%s,花费:%s,剩余:%s。 76 12 64
    222
    总钱数:%s,花费:%s,剩余:%s。 64 57 7
    金额不足!

    程序将会一直卡到这里,这是因为你这样的参数传递方式相当于在start函数没有执行,函数就开始了运行
    '''

     正确的参数传递

    threading.Thread(target=Consumer,args=[ans])
    import random,threading,time
    
    gcondition = threading.Condition()
    Money = 100
    def Create():
        global Money
        num=0
        while 1:
            if num>10:
                break
            gcondition.acquire()
            Money += random.randint(1,100)
            print('生产Money:',Money)
            gcondition.notify_all()
            gcondition.release()
            num+=1
            time.sleep(1)
    
    def Consumer(money):
        global Money
        num = 0
        while 1:
            if num>2:
                break
            gcondition.acquire()
            while Money<money:
                print('金额不足!')
                time.sleep(1)
                gcondition.wait()
            Money-=money
            print('总钱数:%s,花费:%s,剩余:%s。',Money+money,money,Money)
            gcondition.release()
            num+=1
            time.sleep(1)
    
    
    def main():
        the_list = []
        for i in range(1, 3):
            ans = random.randint(1, 100)
            # 参数传递要这样,可不能写成Thread(target=Consumer(ans))
            t1 = threading.Thread(target=Consumer,args=[ans])
            #the_list.append(t1)
            t1.start()
        for i in the_list:
            i.start()
        print('---------------------')
    
        for i in range(1, 3):
            t1 = threading.Thread(target=Create)
            t1.start()
    
    
    
    if __name__ == '__main__':
        main()
    
    '''
    总钱数:%s,花费:%s,剩余:%s。 222
    100 10 90
    总钱数:%s,花费:%s,剩余:%s。 90 17 ---------------------
    73
    生产Money: 99
    生产Money: 141
    生产Money: 162
    总钱数:%s,花费:%s,剩余:%s。 162 17 145
    总钱数:%s,花费:%s,剩余:%s。 145 10 135
    生产Money: 164
    生产Money: 228
    总钱数:%s,花费:%s,剩余:%s。 228 17 211
    总钱数:%s,花费:%s,剩余:%s。 211 10 201
    生产Money: 203
    生产Money: 249
    生产Money: 276
    生产Money: 321
    生产Money: 342
    生产Money: 387
    生产Money: 475
    生产Money: 501
    生产Money: 596
    生产Money: 682
    生产Money: 731
    生产Money: 823
    生产Money: 888
    生产Money: 975
    生产Money: 1025
    生产Money: 1056
    生产Money: 1129
    '''

    六、join函数

    如果一个线程在执行过程中要调用另外一个线程,并且等到其完成以后才能接着执行,解决方法就是“那么在调用这个线程时可以使用被调用线程的join方法。”

    下面先说一下setDeamon()吧:
    其实主线程并不会结束setDeamon(True)的线程,而是当主线程执行完毕之后不会再去关注setDeamon(True)的线程。
    所以setDeamon(True)的线程的结果是我们无法获取到的,类似于爱咋咋地?不管你输出什么,我都不看,主线程跑
    完就结束整个python process。
    而setDeamon(False)的线程会一直受到主线程的关注,就算主线程跑完了也会等setDeamon(False)的线程跑完然后
    再结束整个python process。
    所以说,就算setDeamon(True)的线程在主线程之后跑完,但如果在setDeamon(False)的线程之前跑完的话,也是会
    输出结果的,而不是被所谓的主线程结束就杀死setDeamon(False)的线程。

    看一下不同setDeamon运行结果:

    #coding:utf-8
    import threading
    import time
    
    def action(arg):
        for i in range(2):
            print('sub thread start!the thread name is:%s    ' % threading.currentThread().getName())
            print('the arg is:%s   ' %arg)
            time.sleep(1)
    
    for i in range(4):
        t =threading.Thread(target=action,args=(i,))
        t.setDaemon(True)
        t.start()
    
    print('main_thread end!')
    
    '''
    setDaemon(True)的输出:
    sub thread start!the thread name is:Thread-1    
    the arg is:0   
    sub thread start!the thread name is:Thread-2    
    the arg is:1   
    sub thread start!the thread name is:Thread-3    
    the arg is:2   
    sub thread start!the thread name is:Thread-4    
    the arg is:3   
    main_thread end!
    '''
    '''
    setDaemon(False)的输出:
    sub thread start!the thread name is:Thread-1    
    the arg is:0   
    sub thread start!the thread name is:Thread-2    
    the arg is:1   
    sub thread start!the thread name is:Thread-3    
    the arg is:2   
    sub thread start!the thread name is:Thread-4    
    the arg is:3   
    main_thread end!
    sub thread start!the thread name is:Thread-2    sub thread start!the thread name is:Thread-1    
    the arg is:0   
    
    the arg is:1   
    sub thread start!the thread name is:Thread-3    
    the arg is:2   
    sub thread start!the thread name is:Thread-4    
    the arg is:3   
    '''

    join使用的程序正确书写方法:

    #coding:utf-8
    import threading
    import time
    
    def action(arg):
        time.sleep(1)
        print('sub thread start!the thread name is:%s    ' % threading.currentThread().getName())
        print('the arg is:%s   ' %arg)
        time.sleep(1)
    
    #不正确写法,会导致多线程顺序执行,失去了多线程的意义
    for i in range(4):
        t =threading.Thread(target=action,args=(i,))
        t.setDaemon(True)
        t.start()
        t.join()
    
    #正确写法
    thread_list = []    #线程存放列表
    for i in range(4):
        t =threading.Thread(target=action,args=(i,))
        t.setDaemon(True)
        thread_list.append(t)
    
    for t in thread_list:
        t.start()
    
    for t in thread_list:
        t.join()
    print('main_thread end!')
  • 相关阅读:
    Snagit文字提取捕获技巧
    Snagit长截图或完整截图技巧
    Snagit基于图像模板预制图片布局
    Snagit从图片创建视频的技巧
    截图工具Snagit试用免费激活方法
    Camtasia快捷键大全
    Axure RP快捷键指令汇总
    113资讯网:安装程序进入Admin后台出现:SQLSTATE[HY000] [1045] Access denied for user'root'@'localhost' (using password: YES)
    部署LNMP环境——Yum安装(113资讯网)
    会过日子是什么样
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13432359.html
Copyright © 2020-2023  润新知