• Python 第三十五章 线程 构建线程+线程开启速度+线程pid+数据共享+join+互斥锁+守护线程+其他方法


    线程基本理论

    """
    1.线程是:
    一条流水线的工作流程
    进程:在内存中开启一个进程空间,将主进程的所有的资源数据复制一份,然后调用cpu去执行
    具体描述:
    在内存中开启一个进程空间,将主进程的所有的资源数据复制一份,然后调用线程去执行代码
    ***进程是资源单位,用于划分空间
    ***线程是执行单位,用于执行,线程是CPU中最小的执行单位
    
    开启一个进程的过程:
    进程会在内存中开辟一个进程空间,将主进程的资数据全部复制一份,线程会执行里面的代码
    
    2.线程vs进程
        1.开启进程的开销大,比开启线程的开销大很多
        2.开启线程的速度非常快,快到几十倍到上百倍
        3.线程与线程之间可以共享数据,进程与进程之间需要借助队列等方法实现通信
        进程内部的数据是共享的,进程里面的所有线程
        进程与进程之间是有隔离的,利用queue队列可以通信
        
    总结:
    线程:开销小,执行速度快,同一个进程下的线程资源内存级别可共享
    进程:开销大,执行速度慢,不同进程下的数据内存级别不共享,只能通过队列通信
    
    3.线程的应用:
        并发:一个cpu看起来像是同时执行多个进程
        单个进程下开启是哪个线程:
        开启三个进程并发的执行任务
        一般使用多线程进行开发
        
        使用进程还是使用线程:
        一个软件:例如文件编辑器
        1.输入文字
        2.在屏幕中显示
        3.保存在磁盘中
        这个时候开启多线程就会非常好用了,优点:
        数据可以共享,开销小,速度快
        
    4.主线程和子线程的关系:  
    主线程和子线程没有地位之分,但是一个进程,最少需要一个主线程执行任务,当执行完成,
    主线程需要等待其他子进程执行完成,才能结束本线程
    """
    

    线程相关方法

    开启线程的两种方式

    # 第一种方式 函数方法
    from threading import Thread
    import time
    def task(name):
        print(f'{name} is running')
        time.sleep(1)
        print(f'{name} is gone')
    
    # 线程可以不再main下面写,便于理解还是写上吧
    
    if __name__ =='__main__':
        t1 = Thread(target=task,args=('zs',)) # 涉及到代码都是主线程执行
        t1.start()
        print('==主线程') # 线程是没有主次之分
    
    # 第二种方式 类方法
    from threading import Thread
    import time
    class MyThread(Thread):
        def __init__(self,name,l1,ls1):
            super().__init__()
            self.name = name
            self.l1 = l1
            self.ls1 = ls1
        def run(self):
            print(f'{self.name,self.l1,self.ls1} is running')
            time.sleep(1)
            print(f'{self.name,self.l1,self.ls1} is gone')
    if __name__ =='__main__':
        t1 = MyThread('zs',[1,2,3],'11')
        t1.start()
        print('==主进程')
    from threading import Thread
    from multiprocessing import Process
    import time
    def task(name):
        print(f'{name} is running')
        time.sleep(1)
        print(f'{name} is gone')
    
    # 线程可以不再main下面写,便于理解还是写上吧
    
    if __name__ =='__main__':
        # 在主进程下开启主线程
        t1 = Process(target=task,args=('zs',)) # 涉及到代码都是主线程执行
        t1.start()
        print('==主线程') # 线程是没有主次之分
    

    多线程多进程开启的速度区别

    """
    多线程多进程开启的速度区别
    开启速度上,线程开启比进程快很多
    """
    # 多线程启动速度慢一些
    from multiprocessing import Process
    import os
    import time
    
    def task():
        print(f'子进程{os.getpid()} is running')
        print(f'子进程{os.getpid()} is gone')
    
    if __name__ == '__main__':
        start_time = time.time()
        t = Process(target=task)
        t.start()
        t1 = Process(target=task)
        t1.start()
        t2 = Process(target=task)
        t2.start()
        t3 = Process(target=task)
        t3.start()
        print(f'主进程{os.getppid()}结束') # 进程有主次之分,运行速度比线程慢
        print(f'{time.time()-start_time}')
    # 输出
    # 子进程19516 is running
    # 子进程19516 is gone
    # 主进程590结束
    # 0.009748220443725586
    # 子进程19517 is running
    # 子进程19517 is gone
    # 子进程19518 is running
    # 子进程19518 is gone
    # 子进程19519 is running
    # 子进程19519 is gone
    
    # 多线程执行速度快
    from threading import Thread
    from threading import activeCount
    import time
    import os
    def task():
        print(f'子线程{os.getpid()} is running')
        print(f'子线程{os.getpid()} is gone')
    
    if __name__ == '__main__':
        start_time = time.time()
        t = Thread(target=task)
        t.start()
        t1 = Thread(target=task)
        t1.start()
        t2 = Thread(target=task)
        t2.start()
        t3 = Thread(target=task)
        t3.start()
        print(f'主线程{os.getpid()}结束') # 线程没有主次之分 几乎同时执行完
        print(f'{time.time()-start_time}')
    # 输出
    # 子线程19533 is running
    # 子线程19533 is gone
    # 子线程19533 is running
    # 子线程19533 is gone
    # 子线程19533 is running
    # 子线程19533 is gone
    # 子线程19533 is running
    # 子线程19533 is gone
    # 主线程19533结束
    # 0.0005669593811035156
    
    

    线程进程pid

    from threading import Thread
    import os
    def task():
        print(f'{os.getpid()}')
        print(f'{os.getpid()}')
    
    if __name__ == '__main__':
        t = Thread(target=task)
        t.start()
        t.join()
        print(f'{os.getpid()}') # 同一个进程下,线程的pid都是一样的
    # 输出
    # 19135
    # 19135
    # 19135
    
    

    同一进程内线程是共享数据

    from threading import Thread
    x = 3
    def task():
        """
        修改全局变量的值
        :return:
        """
        global x
        x = 100
    
    if __name__ == '__main__':
        t = Thread(target=task)
        t.start()
        t.join()
        print(f'{x}') # 同一个进程内,线程之间的数据是共享的
    # 输出100
    

    线程的其他方法

    from threading import Thread
    from multiprocessing import Process
    from threading import currentThread
    from threading import enumerate
    from threading import activeCount
    import time
    import os
    x = 3
    def task():
        global x
        x = 100
        time.sleep(1)
        print(os.getpid())
    
    # 对象的属性
    if __name__ =='__main__':
        t1 = Thread(target=task) # t1 线程
        # name 设置线程名
        t1.start()
        time.sleep(2)
        print(t1.isAlive()) # 判断线程是否活着
        # False
    
        print(t1.getName()) # 获取线程名
        # Thread-1
    
        t1.setName('zs') # 设置线程名**
        print(t1.name)
        # zs
    
        print(f'==主线程{x}') # 同一进程内的资源数据对于这个进程的多线程来说是共享的
    
    # 模块的属性
    if __name__ =='__main__':
        t1 = Thread(target=task,name=('zs')) # 涉及到代码都是主线程执行
        t2 = Thread(target=task,name=('zs2')) # 涉及到代码都是主线程执行
        t1.start()
        t2.start()
        print(currentThread()) # 获取当前线程的对象
        # <_MainThread(MainThread, started 140736975586240)>
    
        print(enumerate()) # 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
        # [<_MainThread(MainThread, started 140736975586240)>, <Thread(zs, started 123145558224896)>, <Thread(zs2, started 123145563480064)>]
    
        print(activeCount()) # ***返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
        # 3
    
        print('==主线程')
    

    join

    # join 阻塞 告诉主线程要等待子线程执行完毕再执行主线程
    # join 将执行的子线程和主线程变成串行,子线程和子线程之间是并行
    # .start().join().start().join().start().join()是串行
    # .srart().start().start().join().join().join()是并发
    # for i in t  t.start()  for i in t1 t1.join() 是并发
    from threading import Thread
    import time
    def task(name):
        print(f'{name} is running')
        time.sleep(1)
        print(f'{name} is gone')
    
    if __name__ == '__main__':
        start_time = time.time()
        t1 = Thread(target=task,args=('海狗1',))
        t2 = Thread(target=task,args=('海狗2',))
        t3 = Thread(target=task,args=('海狗3',))
        # 串行
        t1.start()
        t1.join()
    
        t2.start()
        t2.join()
    
        t3.start()
        t3.join()
        print(f'===主线程{time.time()-start_time}') # 线程没有主次之分
    
    # 输出
    # 海狗1 is running
    # 海狗1 is gone
    # 海狗2 is running
    # 海狗2 is gone
    # 海狗3 is running
    # 海狗3 is gone
    # ===主线程3.0098721981048584
    
    from threading import Thread
    import time
    def task(name):
        print(f'{name} is running')
        time.sleep(1)
        print(f'{name} is gone')
    
    if __name__ == '__main__':
        start_time = time.time()
        t1 = Thread(target=task,args=('海狗1',))
        t2 = Thread(target=task,args=('海狗2',))
        t3 = Thread(target=task,args=('海狗3',))
    
        # 并发
        t1.start()
        t2.start()
        t3.start()
        t1.join()
        t2.join()
        t3.join()
        print(f'===主线程{time.time()-start_time}') # 线程没有主次之分
    # 输出
    # 海狗1 is running
    # 海狗2 is running
    # 海狗3 is running
    # 海狗1 is gone
    # 海狗2 is gone
    # 海狗3 is gone
    #
    # ===主线程1.0116689205169678
    

    守护线程

    # 守护线程:守护非子线程和主线程
    # 什么时候结束:
    # 如果守护线程的生命周期小于其他线程,会先结束
    # 否则等待其他非守护子进程以及主线程结束之后结束
    
    from threading import Thread
    import time
    
    def sayhi(name):
        print('你滚!')
        time.sleep(2)
        print('%s say hello' %name) # 先执行子线程
    
    if __name__ == '__main__':
        t = Thread(target=sayhi,args=('egon',))
        # t.setDaemon(True) #必须在t.start()之前设置
        t.daemon = True
        t.start()  # 线程的开启速度要比进程快很多
    
        print('主线程') # 最后执行主线程
    # 输出
    # 你滚!
    # 主线程
    
    
    # 守护子线程睡的短,非子线程睡的久,其他非子线程还没有结束,守护子线程也未结束,继续执行,end123输出,都结束完了,主线程结束
    from threading import Thread
    import time
    
    def foo():
        """
        先执行子线程
        :return:
        """
        print(123)  # 1 先打印123
        time.sleep(1) # 子线程睡了,只睡1秒,下面的不执行,开始走t2
        print("end123")  # 4 接着主进程的输出,再打印end123,继续往下走,走t2
    
    def bar():
        """
        再执行子线程
        :return:
        """
        print(456)  # 2 再打印456
        time.sleep(3) # 子进程睡了,睡了3秒,下面不执行
        print("end456")  # 5 接着t1的输出,再打印end456
    
    
    t1=Thread(target=foo)
    t2=Thread(target=bar)
    
    t1.daemon=True # 只设置t1守护主线程
    t1.start() # 启动t1
    t2.start()
    print("main-------")  # 3 # 最后执行主线程 最后走主进程 主进程监测到子进程还没有结束,继续走,此时t1的守护时间已过,继续执行t1
    # 输出
    # 123
    # 456
    # main-------
    # end123
    # end456
    
    # 守护子线程睡的久 其他非子线程和主线程都执行完了,守护子线程也结束,不再执行守护子线程的代码,end123不输出
    from threading import Thread
    import time
    
    def foo():
        print(123)  # 1
        time.sleep(3)
        print("end123")
    
    def bar():
        print(456)  # 2
        time.sleep(1)
        print("end456")  # 4
    
    
    t1=Thread(target=foo)
    t2=Thread(target=bar)
    
    t1.daemon=True
    t1.start()
    t2.start()
    print("main-------")  # 5
    # 输出
    # 123
    # 456
    # main-------
    # end456
    
    
    
    # 守护子线程和非子线程睡的时间一样,非子线程和主线程都结束了,守护线程也结束了,不再执行守护子线程的代码,end123不输出
    from threading import Thread
    import time
    
    def foo():
        print(123)
        time.sleep(3)
        print("end123")
    
    def bar():
        print(456)
        time.sleep(1)
        print("end456")
    
    
    t1=Thread(target=foo)
    t2=Thread(target=bar)
    
    t1.daemon=True
    t1.start()
    t2.start()
    print("main-------")
    # 输出
    # 123
    # 456
    # main-------
    # end456
    

    互斥锁

    from threading import Thread
    import time
    import random
    
    x = 100 # x被修改 x = 99
    def task():# ①
        global x # 再执行修改全局变量 x = 99
        temp = x # ③ 先执行temp = 100,100个100
        time.sleep(random.randint(1,3)) # 开始随机睡,有一个temp醒得快,开始往下走,其他的temp还在睡
        # 其他的temp开始醒来,继续往下执行 都执行temp = 100-1 = 99(执行速度快会是99,慢的话,99~0都有可能)
        temp = temp -1 # temp = 100-1 = 99
        x = temp # x = 99
        print(f'这些是子线程{x}')
    
    # 先走函数def task ,函数里面的代码不执行
    if __name__ == '__main__': # 走if开始执行接口
        l1 = [] # 定义一个列表
        for i in range(100): # ② 循环i 100次
            t = Thread(target = task) # Thread(target = task)实例化一个子线程t,Thread是线程类 target = task 将task传入实例化对象中
            l1.append(t) # 将实例化对象加入l1列表中,得到100个实例化对象
            t.start() # start()调用函数,开始启动task里面的代码
        print('开始启动子线程')
    
        for i in l1: # ④ 循环100个实例化对象
            i.join() # 每次都执行的子线程都会阻塞不执行主线程,使用for i in 其他的子线程是并发执行
        print('阻塞子线程')
        print(f'主线程{x}') # ⑤主线程99
    
    
    
    from threading import Thread
    import time
    import random
    
    x = 100
    def task():
        time.sleep(random.randint(1,2))
        global x
        temp = x
        time.sleep(random.randint(1,3))
        temp = temp -1
        x = temp
    
    
    if __name__ == '__main__':
        l1 = []
        for i in range(100):
            t = Thread(target = task)
            l1.append(t)
            t.start()
    
        for i in l1:
            i.join()
        print(f'主线程{x}') # 主线程98
    
    
    from threading import Thread
    import time
    import random
    
    x = 100
    def task():
        global x
        temp = x
        temp = temp -1
        x = temp
    
    
    if __name__ == '__main__':
        l1 = []
        for i in range(100):
            t = Thread(target = task)
            l1.append(t)
            t.start()
    
        for i in l1:
            i.join()
        print(f'主线程{x}') # 主线程0
    # 多个任务共抢一个资源数据,保证数据的安全目的,要让其串行,串行可以用互斥锁
    
    from threading import Thread
    from threading import Lock
    import time
    import random
    
    x = 100
    def task(lock):
        lock.acquire()
        global x
        temp = x
        time.sleep(0.01)
        temp = temp -1
        x = temp
        lock.release()
    
    
    if __name__ == '__main__':
        mutex = Lock()
        l1 = []
        for i in range(100):
            t = Thread(target = task,args=(mutex,))
            l1.append(t)
            t.start()
    
        time.sleep(3)
        print(f'主线程{x}') #主线程0
    
  • 相关阅读:
    9.17
    9.14
    9.13
    9.13
    9.11
    9.28
    10 .19 知识点
    redux
    react路由
    react的三大属性
  • 原文地址:https://www.cnblogs.com/zhangshan33/p/11402376.html
Copyright © 2020-2023  润新知