42.线程概念及线程池

进程:是CPU分配资源的最小单位

  • CPU时间片:CPU处理的时间长度
  • 进程是CPU分配资源的最小单位
    • 光有进程没有办法高效里用CPU资源
    • 处理进程等待时,进程会做IO等待,从而浪费时间,无法高效利用cpu
  • 内存独立:
    • 进程切换了,彼此多个进程不会影响
    • A,B,C,3个进程相互独立,不管ABC怎么切换,数据不会乱
    • 一个进程挂掉,其他进程不会有事情

线程:CPU执行的最小单位

  • 轻量级的进程:线程是**内存共享**
    • CPU寄存器,计算器
    • 切换简单,CPU在切换执行任务的时候,损耗的时间少
    • 但是由于线程存在GIL锁(Golbal Lock),维持全局的线程同步执行,导致最大的缺点就是没有办法实现真正并发
    • 最大的优点是线程等待时IO可以切换,高效利用CPU资源
  • GIL锁的存在由此推论出Cpython中的多线程执行就是同步的:按照顺序,一个个来
  • 进程:PID Process
  • 线程也有:TID Thread
    • 只在当前的内存空间下有用
  • 线程如果父进程退出,那么全部子线程,都会退出
    • 主线程死亡,子线程死亡
    • 为了保持线程的稳定性,主线程一般不要做大事,不要业务处理,只做开启任务
    • 没有孤儿线程,僵尸线程会有但是无所谓不重要
  • 数据通信:
    • 本身内存共享,list,dict,str,int,这些数据都可以直接共享
  • GIL:
    • 大锁,全局锁,直接锁掉线程,维持全局的线程同步执行,影响并发,未来说不定这个东西就没有了
  • from threading import Thread
    • Process(target,args,)
    • t = Thread(target,args,name,kwargs)
      • t.start() 真正开启线程
      • t.join() 回收线程资源
  • #线程创建
    from threading import Thread
    import time
    def work_a(a):
        for var in range(100000):
            a[0] += 1
    def work_b(a):
        for var in range(100000):
            a[0] = a[0] * 3
    def work_c(a):
        for var in range(50000):
            a[0] = a[0] - 1
    def main():
        a = [1]
        start = time.time()
        t = Thread(target=work_a,args=(a,))
        t.start()
        t1 = Thread(target=work_b,args=(a,))
        t1.start()
        t2 = Thread(target=work_c,args=(a,))
        t2.start()
        for var in [t,t1,t2]:
            var.join()
        end = time.time()
        print('耗时:%.2f' % (end - start))
    if __name__ == "__main__":
        main()
    

    运行结果:

    耗时:0.49
    

     

  • #线程数据共享,数据都可以直接共享
    from threading import Thread
    def work_a(a):
        a[0] = 'a'
    def main():
        a = [1]
        t = Thread(target=work_a,args=(a,))
        t.start()
        t.join()
        print(a)
    if __name__ == "__main__":
        main()
    

    运行结果:

    ['a']
  • 列外:

    • 只有纯计算没有IO的时候,多线程等同于单进程
      • 甚至是多线程效率低于单进程
    • 多进程:多核心电脑
      • 计算密集的时候,多进程最快-->单进程-->多线程
    • 多线程:
      • IO密集
      • 比如:操作文件,QQ聊天的时候用多线程比较好 

线程池:

  • from multiprocessing.pool import ThreadPool 
    • 引入线程池模块
  • thread_pool= ThreadPool(5)             
    • 创建5个线程池
  • p=thread_pool.apply_async(func,args,)   
    • 非阻塞行为,并发的,无序的 
    • 非阻塞的会返回一个抽象的数据,调用值得时候需要用get函数p.get()
  • thread_pool.close(),thread_pool.join() 
    • 最后关闭跟回收线程
  • def work_a(a):
        for var in range(100000):
            a[0] += 1
        else:
            return a[0]
    def main():
        a = [1]
        start = time.time()
        thread_pool= ThreadPool(1)
        p=thread_pool.apply_async(func=work_a,args=(a,))
        thread_pool.close()
        thread_pool.join()
        end = time.time()
        print('耗时:%.2f' % (end - start))
        print(p.get())
    if __name__ == "__main__":
        main()

   运行结果:

  • 耗时:0.10
    100001
    

     

  • import time,sys
    from threading import Thread
    from multiprocessing.pool import ThreadPool
    
    def work_a(a):
        for var in a:
            print('生产者:',var)
            sys.stdout.flush()
            time.sleep(1)
    def work_b(a):
        for var in a:
            print('消费者:',var)
            sys.stdout.flush()
            time.sleep(1)
    def main():
        a=[1,2,3,4,5]
        thread_pool=ThreadPool(2)
        thread_pool.apply_async(func=work_a,args=(a,))
        thread_pool.apply_async(func=work_b,args=(a,)) 
        thread_pool.close()
        thread_pool.join()
    if __name__ == "__main__":
        main()
    

    运行结果:  

  • 生产者: 1
    消费者: 1
    生产者: 2
    消费者: 2
    生产者: 3
    消费者: 3
    生产者: 4
    消费者: 4
    生产者: 5
    消费者: 5
    

      

      

 

posted on 2019-01-20 14:36  走路带风的帅界扛把子  阅读(157)  评论(0编辑  收藏  举报