zoukankan      html  css  js  c++  java
  • 线程的理论

    线程的理论知识

    1.什么是线程

    ​ 一条流水线的工作流程

    之前描述的进程 : 在内存中开启一个进程空间,然后将主进程的所有资源数据复制一份,然后调用 CPU 执行这些代码

    之前描述的进程不够具体,具体的应该是这样: 在内存中开启一个进程空间,然后将主进程的所有资源数据复制一份,然后调用线程去执行这些代码

    进程是资源单位,线程是执行单位(线程是 CPU 最小的执行单位,进程是由线程执行的)

    以后你描述一个开启一个进程 :在内存中开启一个进程空间,然后将主进程的所有资源数据复制一份,然后调用线程去执行这些代码

    2.线程 VS 进程

    1. 开启进程的开销非常大,比开启线程的开销大很多
    2. 开启线程的速度非常快,要大几十甚至几百倍
    3. 线程线程之间可以共享数据,进程进程之间必须借助队列等方法实现通信

    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")
    if __name__ == '__main__':
        t1 = Thread(target = task,args=("海狗",))
        t1.start()
        print("====主线程")
    #  执行的速度非常快
    

    第二版

    没传参数的情况

    from threading import Thread
    import time
    class MyThread(Thread):
        def run(self):
            print(f"{self.name} is running")
            time.sleep(1)
            print(f"{self.name} is gone")
    if __name__ == '__main__':
        t1 = MyThread ()
        t1.start()
        print("====主线程")
        
    '''
    Thread-1 is running
    ====主线程
    Thread-1 is gone    类似于进程中不传 self.name 输出的结果是 process - 1
    '''
    

    传参数的情况

    from threading import Thread
    import time
    class MyThread(Thread):
        def __init__(self,name,l1,s1):
            super().__init__()
            self.name = name
            self.l1 = l1
            self.s1 = s1
    
        def run(self):
            print(f"{self.name} is running")
            time.sleep(1)
            print(f"{self.name} is gone")
    if __name__ == '__main__':
        t1 = MyThread ('魏无羡',[1,2,3],"180")
        t1.start()
        print("====主线程")
    
    '''
    魏无羡 is running
    ====主线程
    魏无羡 is gone
    '''
    

    5.线程进程 pid

    主线程和子线程没有地位之分,这就引出了一个问题?

    一个进程究竟谁在干活?

    一个主线程在干活,当干完活了,你得等待其他线程干完活之后,才能结束本线程.

    一个进程下的主线程和主进程共用一个 pid 可以这样理解,他们在一个空间里嘛

    from threading import Thread
    import os
    def task():
        print(os.getpid())
    if __name__ == '__main__':
        t1 = Thread(target = task)
        t2 = Thread(target = task)
        t1.start()
        t2.start()
        print(f"主线程{os.getpid()}")
    '''
    59998
    59998
    主线程59998   不变不变
    

    6.同一个进程,线程是共享数据的

    1. 进程:子进程和主进程是隔离的
    2. 线程:共享
    3. 同一进程的资源数据对于这个进程的多个线程来说是共享的
    from threading import Thread
    import os
    x = 3
    def task():
        global x
        x = 100
    if __name__ == '__main__':
        t1 = Thread(target = task)
        t2 = Thread(target = task)
        t1.start()
        t2.start()
        print(f"主线程:{x}")
    #  主线程:100     你看改变了  不是
    

    7.线程的其他方法

    几个方法全部都在里了哦

    from threading import Thread
    from threading import currentThread
    from threading import enumerate
    from threading import activeCount
    import os
    import time
    x = 3
    def task():
        time.sleep(1)
        print(666)
    if __name__ == '__main__':
        t1 = Thread(target = task,name = '线程 1')
        t2 = Thread(target = task,name = '线程 2')
        #  设置线程名
        t1.start()
        t2.start()
    
        time.sleep(1)
        print(t1.isAlive())    #  判断线程是否活着  返回 True or False
        # print(t1.getName())  #  获取线程名
        # t1.setName('子线程-1')   #  修改线程名
        # print(t1.name)         #  获取线程名   重要****************************************
    
        # print(currentThread()) # 获取当前线程的对象,并且是主线程哦
        # print(enumerate())   # 返回一个列表,包含所有的线程对象
        # print(activeCount()) #  返回活着的线程数   重要***************************************
        # print(f"===主线程{os.getpid()}")
    

    8.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 = ('海狗',))
        t2 = Thread(target = task,args = ('海狗1',))
        t3 = Thread(target = task,args = ('海狗2',))
        t1.start()
        t2.start()
        t3.start()
    
        t1.join()
        t2.join()
        t3.join()
        print(f"主线程{time.time() - start_time}")
    
    '''
    海狗 is running
    海狗1 is running
    海狗2 is running
    海狗 is gone
    海狗1 is gone
    海狗2 is gone
    主线程1.0073320865631104
    

    串行的情况 : 一个一个的执行

    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 = ('海狗',))
        t2 = Thread(target = task,args = ('海狗1',))
        t3 = Thread(target = task,args = ('海狗2',))
        t1.start()
        t1.join()
        t2.start()
        t2.join()
        t3.start()
        t3.join()
        print(f"主线程{time.time() - start_time}")
    
    '''
    海狗 is running
    海狗 is gone
    海狗1 is running
    海狗1 is gone
    海狗2 is running
    海狗2 is gone
    主线程3.0137791633605957
    '''
    

    回忆一下守护进程

    from multiprocessing import Process
    import time
    def foo():
        print(123)
        time.sleep(1)
        print('end123') #  随着主进程的结束这个就不执行了
    def bar():
        print(456)
        time.sleep(1)
        print('end456')
    if __name__ == '__main__':
        p1 = Process(target = foo)
        p2 = Process(target = bar)
    
        p1.daemon = True
        p1.start()
        p2.start()
        print('===主')
    '''
    ===主
    123
    456
    end456
    '''
    

    我们看一下守护线程,结果很秀

    简单版本的

    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 = ('大黄',))
        t.setDaemon(True)   #  必须在t.start()之前
        # t.daemon = True   这个也是
        t.start()
        print("主线程")
    '''
    你滚
    主线程
    '''
    

    下面两版作对比

    from threading import Thread
    import time
    def foo():
        print(123)
        time.sleep(1)
        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------
    end123
    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
    '''
    

    总结 : 守护线程等待非守护线程以及主线程结束后结束

    PS : 就是主线程等其他进程,守护进程等待主线程

    需要重点理解的,还没加锁的情况

    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, 2))
        temp = temp - 1
        x = temp
    if __name__ == '__main__':
        l1 = []
        for i in range(100):
            t = Thread(target = task)
            l1.append(t)
            t.start()
            #t.join()  这里的结果是串行,自己测试的
        for i in l1:
            i.join()   
            '''
            放在这里的效果相当于并发   就像是之前的那个代码,1  2  3   
            join放在下面  一样  但 要是紧跟着,那就是串行,这里还是并发
            运行速度非常快,一窝蜂全部拿到  x = 100  不是其他人不执行,而是
            结果都是一样的 99
            '''
            print(f"主线程:{x}")
    

    多个任务公抢一个资源时,要让其串行,所以选择加锁

    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  这是最终的结果
    '''
    
  • 相关阅读:
    PhotoshopCS6中文版图像处理实战从入门到精通
    Web安全开发指南
    OpenStack运维指南
    Word/Excel/PPT 2016高效办公实战从入门到精通
    UG NX 8.5中文版基础教程
    Moldflow 2018模流分析从入门到精通:升级版
    数据库与数据处理:Access 2010实现
    iOS开发网络数据之AFNetworking使用1
    AFNetworking2.5使用2
    iOS项目的完整重命名方法图文教程
  • 原文地址:https://www.cnblogs.com/hualibokeyuan/p/11395739.html
Copyright © 2011-2022 走看看