zoukankan      html  css  js  c++  java
  • 多线程

    多线程

    进程和线程

    进程是资源分配的最小单位,线程是CPU调度的最小单位。每一个进程中至少有一个线程。

    进程

    本质上就是一段程序的运行过程(抽象概念)

    最小的资源单位(操作系统分配cpu,内存资源的基本单位)

    线程

    最小的执行单元(实例),是cpu调度和分派的基本单位

    每个线程都有自己的堆栈和局部变量

    线程在同一进程中的各个线程,都可以共享该进程所拥有的资源

    1.一个程序至少有一个进程,一个进程至少有一个线程。(进程可以理解为线程的容器),一个进程里可以开辟多个线程和进程

    2.进程在执行过程中拥有独立的内存单元,而多个线程共享这个进程的内存,从而极大地提高了程序的运行效率

    3.一个线程(主线程创建子线程)可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行

    同一进程中的各个线程,都可以共享该进程所拥有的资源,这首先表现在:所有线程都具有相同的进程id,这意味着,线程可以访问该进程的每一个内存资源;此外,还可以访问进程所拥有的已打开文件、定时器、信号量机构等。由于同一个进程内的线程共享内存和文件,所以线程之间互相通信不必调用内核。

    并发&并行

    并发:系统具有处理多个任务的能力,cpu疯狂切换(单核)

    并行:系统具备同时处理多个任务的能力(多核)

    同步&异步

    同步:我煮饭,我等煮好饭去炒菜--等

    异步:我煮饭的过程中,可以去炒菜--不等

    python解释器的GIL锁

    GIL解决什么问题?

    Python使用引用计数来管理内存,x=1,如果线程执行到1,这个时候垃圾回收线程来执行,会发现x引用计数为0,就会把x给干掉,显然,这样是不对的。

    无论你启多少个线程,你有多少个cpu, Python在执行的时候会淡定的在同一时刻只允许一个线程运行

    一个python进程同一时间只有一个线程能被cpu调用(多核对它基本没有用)

    但是可以开启多个进程,然后每个进程就可以各有一个线程丢给一个cpu,来实现并行

    线程抢占的就是GIL锁

    计算密集型:多进程效率高

    I/O密集型:多线程效率高(IO过程中cpu会有空闲时间,可以利用空闲时间做别的任务)

    多线程或者(多进程+携程)用于IO密集型,如socket,爬虫,web

    多进程用于计算密集型,如金融分析(但是不推荐)

    python中的多线程

    例1

    如下有三个线程,一个主线程,主线程开辟了两个子线程

    主线程最先运行完毕,t1子线程运行了3秒,t2子线程运行了6秒

    整个进程花费了6秒多一点结束

    import threading
    import time
    
    def zx(t,s):
        time.sleep(s)
        print(t)
    
    
    if __name__ == '__main__':
        t1=threading.Thread(target=zx,kwargs={"t":"t1","s":3})
        t1.start()
    
        t1=threading.Thread(target=zx,kwargs={"t":"t2","s":6})
        t1.start()
    
        print("main")
    

    main
    t1
    t2

    Process finished with exit code 0
    例2

    和上面一样的知识点

    import time
    import threading
    
    def music():
        print("开始听歌")
        time.sleep(3)
        print("停止听歌")
    
    def game():
        print("开始玩游戏")
        time.sleep(6)
        print("停止玩游戏")
    
    if __name__ == '__main__':
        t1=threading.Thread(target=music)
        t2=threading.Thread(target=game)
        t1.start()
        t2.start()
    
        print("main")
    
    

    开始听歌
    开始玩游戏
    main
    停止听歌
    停止玩游戏

    Process finished with exit code 0

    常用方法和属性

    threading模块提供的一些方法:
    # threading.currentThread(): 返回当前的线程对象。
    # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
    # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
    
    线程对象方法
    #ident:线程的id
    # run():  线程被cpu调度后自动执行线程对象的run方法
    # start():启动线程活动。
    # isAlive(): 返回线程是否活动的。
    # getName(): 返回线程名。
    # setName(): 设置线程名。
    

    join() 线程等待

    join():在子线程完成运行之前,这个子线程的父线程将一直被阻塞。

    看懂下面代码者,方可大成

    join()相当于,执行完这个子线程,再去执行主线程下面的代码

    import time
    import threading
    
    def music():
        print("开始听歌")
        time.sleep(3)
        print("停止听歌")
    
    def game():
        print("开始玩游戏")
        time.sleep(6)
        print("停止玩游戏")
    
    if __name__ == '__main__':
        t1=threading.Thread(target=music)
        t2=threading.Thread(target=game)
        t1.start()
    
        t1.join()
    
        t2.start()
    
        t2.join()
    
        print("main")
    
    

    开始听歌
    停止听歌
    开始玩游戏
    停止玩游戏
    main

    Process finished with exit code 0

    setDaemon()守护线程

    setDaemon(True):

    将线程声明为守护线程,必须在start() 方法调用之前设置,当我们 在程序运行中,执行一个主线程,主线程运行完毕,想退出时,会检验子线程是否完成。如果子线程未完成,则主线程会等待子线程完成后再退出。但是有时候我们需要的是 只要主线程完成了,不管子线程是否完成,都要和主线程一起退出,这时就可以 setDaemon方法

    例1

    当主线程运行完毕,去检验t1和t2,发现他们都是守护线程,直接退出

    import time
    import threading
    
    def music():
        print("开始听歌")
        time.sleep(3)
        print("停止听歌")
    
    def game():
        print("开始玩游戏")
        time.sleep(6)
        print("停止玩游戏")
    
    if __name__ == '__main__':
        t1=threading.Thread(target=music)
        t2=threading.Thread(target=game)
        t1.setDaemon(True)
        t2.setDaemon(True)
        t1.start()
        t2.start()
        print("main")
    

    开始听歌
    开始玩游戏
    main

    Process finished with exit code 0

    例2

    当主线程运行完毕,去检验t1和t2,发现t1不是守护线程,t2是守护线程,t1耗时3秒,t1执行完毕,直接退出,因为t2耗时6秒,还是守护线程,主线程不用管它

    import time
    import threading
    
    def music():
        print("开始听歌")
        time.sleep(3)
        print("停止听歌")
    
    def game():
        print("开始玩游戏")
        time.sleep(6)
        print("停止玩游戏")
    
    if __name__ == '__main__':
        t1=threading.Thread(target=music)
        t2=threading.Thread(target=game)
        t2.setDaemon(True)
        t1.start()
        t2.start()
        print("main")
    

    开始听歌
    开始玩游戏
    main
    停止听歌

    Process finished with exit code 0

    定时器

    线程延迟执行

    from threading import Thread,Timer
    import time
    
    def task():
        print('线程执行了')
        time.sleep(2)
        print('线程结束了')
    
    t = Timer(4,task) # 过了4s后开启了一个线程
    t.start()
    print("end")
    
    end
    线程执行了
    线程结束了
    
    
  • 相关阅读:
    Individual Contest #1 and Private Training #1
    2016 GDCPC 省赛总结
    HDU 4000 Fruit Ninja(树状数组)
    HDU 4009 Transfer water(最小树形图)
    HDU 5176 The Experience of Love
    HDU 2121 Ice_cream’s world II(无定根最小树形图)
    UVA 11183 Teen Girl Squad(最小树形图)
    POJ 3164 Command Network(最小树形图)
    最小树形图
    UVA 10462 Is There A Second Way Left?(次小生成树)
  • 原文地址:https://www.cnblogs.com/zx125/p/11440563.html
Copyright © 2011-2022 走看看