• 线程相关知识


    1.线程

    #进程是资源分配的最小单位   (包工头)
    #线程是程序调度的最小单位 (工人)

    #线程的缘起
    资源分配需要分配内存空间,分配cpu:
    分配的内存空间存放着临时要处理的数据等,比如要执行的代码,数据
    而这些内存空间是有限的,不能无限分配
    目前配置高的主机,5万个并发已是上限.线程概念应用而生.

    #线程的特点
    线程是比较轻量级,能干更多的活,一个进程中的所有线程资源是共享的.
    一个进程至少有一个线程在工作

    线程的缺陷

    #线程可以并发,但是不能并行(同一个进程下的多个线程不能分开被多个cpu同时执行)
    #原因:
    python是解释型语言,执行一句编译一句,而不是一次性全部编译成功,不能提前规划,都是临时调度
    容易造成不同的cpu却反复执行同一个程序.所以加了一把锁叫GIL
    全局解释器锁(Cpython解释器特有) GIL锁:同一时间,一个进程下的多个线程只能被一个cpu执行

    #想要并行的解决办法:
    (1)用多进程间接实现线程的并行
    (2)换一个Pypy,Jpython解释器

    #程序分为计算密集型和io密集型
    对于计算密集型程序会过度依赖cpu,但网页,爬虫,OA办公,这种io密集型的程序里,python绰绰有余

    1.1进程中可以包含多个线程

    import os,random,time
    from threading import Thread
    from multiprocessing import Process
    
    def func(num):
        time.sleep(random.uniform(0.1,1))
        print("子线程",num ,os.getpid())
    
    for i in range(10):
        t = Thread(target=func,args=(i,))
        t.start()

      从上代码可以看出,主线程加子线程一共有11个线程!

    1.2 并发多线程 和 多进程,谁的速度快  => 多线程

    import os,random,time
    from threading import Thread
    from multiprocessing import Process
    
    def func(num):
        print("子线程",num ,os.getpid())
    
    if __name__ == '__main__':
        startime = time.perf_counter()
        lst = []
    
        for i in range(1000):
            t = Thread(target=func,args=(i,))
            t.start()
            lst.append(t)
    
        for i in lst:
            # print(i)
            i.join()
    
        endtime = time.perf_counter()
        print("多线程执行的时间:",endtime-startime) #  0.31189374899986433
    
        # 多进程的执行时间
        startime = time.perf_counter()
        lst = []
        for i in range(1000):
            p = Process(target=func,args=(i,))
            p.start()
            lst.append(p)
    
        for i in lst:
            i.join()
    
        endtime = time.perf_counter()
        print("多进程执行的时间:",endtime-startime) # 多进程执行的时间: 2.034676988994761

    1.3多线程共享同一份进程资源

    import os,random,time
    from threading import Thread
    from multiprocessing import Process
    
    num = 100
    lst = []
    def func():
        # 异步并发程序
        time.sleep(1)
        global num
        num -= 1
    
    for i in range(100):
        t = Thread(target=func)
        t.start()
        lst.append(t)
    
    for i in lst:
        i.join()
    
    print(num)

      注意:线程与线程之前是异步并发的

    1.4 线程相关的函数

      线程.is_alive() 检测线程是否仍然存在
      线程.setName() 设置线程名字
      线程.getName() 获取线程名字
      1.currentThread().ident 查看线程id号
      2.enumerate() 返回目前正在运行的线程列表
      3.activeCount() 返回目前正在运行的线程数量

    import os,random,time
    from threading import Thread
    from multiprocessing import Process
    
    def func():
        # pass
        time.sleep(0.5)
    t = Thread(target=func)
    
    print(t) # <Thread(Thread-1, initial)>
    t.start()
    print(t.is_alive()) # True
    print(t.getName()) # Thread-1
    t.setName("producer_wang1号")
    print(t.getName()) # producer_wang1号
    
    # (2).enumerate()  放回目前正在运行的线程列表
    from threading import enumerate
    from threading import currentThread
    
    def func():
        print("子进程:",currentThread().ident) # 查看线程id号
        time.sleep(0.5)
    
    for i in range(10):
        t = Thread(target=func)
        t.start()
    
    print(enumerate())
    print(len(enumerate())) # 11
    
    # (3).activeCount()  返回目前正在运行的线程数量 (了解)
    from threading import activeCount
    from threading import currentThread
    def func():
        print("子进程:",currentThread().ident)
        time.sleep(0.5)
    
    for i in range(10):
        t = Thread(target=func)
        t.start()
    
    print(activeCount()) # 11

    2.守护线程

       等待所有线程全部执行结束之后,再终止。守护所有线程。主程序默认等待所有的子线程

    from threading import Thread
    import time
    def func1():
        while True:
            time.sleep(0.5)
            print("我是子线程func1函数")
    
    def func2():
        print("func2 start...")
        time.sleep(3)
        print("func2 end ...")
    
    t1 = Thread(target=func1)
    # 设置守护线程,在start调用之前进行设置 setDaemon
    t1.setDaemon(True)
    t1.start()
    
    t2 = Thread(target=func2)
    t2.start()
    
    print("我是主线程。。。")

    3.线程锁lock

    from threading import Thread,Lock
    n = 0
    def func1(lock):
        global n
    
        for i in range(10000):
            lock.acquire()
            # 写法一
            n -=1
            lock.release()
    def func2(lock):
        global n
        for i in range(10000):
            # 写法二
            with lock:
                n += 1
    if __name__ == '__main__':
        # 创建一把锁
        lock = Lock()
        lst = []
        for i in range(10):
            # 10个线程专门负责加1
            t1 = Thread(target=func1,args=(lock,))
            # 10个线程专门负责减1
            t2 = Thread(target=func2,args=(lock,))
            t1.start()
            t2.start()
            lst.append(t1)
            lst.append(t2)
        for i in lst:
            i.join()
        print("主进程执行结束。。。")
        print(n)

    4.信号量 Semaphore

    from threading import Semaphore,Thread
    import time
    def func(i,sem):
        with sem:
            print(i)
            time.sleep(10)
    
    sem = Semaphore(6) # 批量上锁6把
    for i in range(20):
        Thread(target=func,args=(i,sem)).start()
  • 相关阅读:
    ViewDragHelper: ViewDragHelper的使用
    HashMap存入和取出数据顺序不一致
    服务器raid卡、磁盘缓存的配置策略
    关于LVS+Nginx为什么会被同时使用的思考
    JDT Icons-eclipse图标大全
    EclipseHTML/JS/CSS/JS 代码自动提示
    eclipse maven设置本地仓库
    mysql 补零操作(zerofill)
    mysql datetime字段默认值 设置 当前时间
    Timed out as no activity
  • 原文地址:https://www.cnblogs.com/youhongliang/p/11871924.html
Copyright © 2020-2023  润新知