zoukankan      html  css  js  c++  java
  • 线程

    一、基本概念

      程序:程序可以理解成是一系列的指令集,程序是静态。
      进程:当程序运行时,会创建一个进程。
      线程:进程基本执行单元,一个进程至少有一个线程。

    进程和线程之间的关系:

      一个线程只属于一个进程,一个进程中可以包含很多线程,只有一个主线程。

    进程资源、线程的资源对比:

      进程具有独立的空间和系统资源。
      线程没有独立的空间和系统资源,同一个进程下的多个线程共享该进程中的资源的。

      问题:多线程中对于共享资源修改的问题-----多线程同步问题----线程不安全。

    二、多线程

      单核cpu下:并行:宏观,微观上来看,仍然是串行
      多核cpu:真正并行

    计算机cpu执行,IO操作场合

      计算密集型:不适合单核cpu多线程
      io密集型:适合单核cpu的多线程

    多线程的缺点

      (1)线程本身也是程序,也是需要占内存,线程越多,占用的内存就越多 。
      (2)多线程之间的调用需要协调管理,需要cpu进行线程的跟踪
      (3)重要:多线程之间对共享资源的访问有影响,必须解决线程共享资源的问题,否则会导致数据的不一致。

    三、线程的创建

    三种方式

    1. 使用threading模块创建,通过指定target和args参数,创建线程
    2. 使用Thread类,重写run方法
    3. 使用线程池(高阶)

    方式1

    import time
    import threading
    # def mission(end):
    #     for i in range(end):
    #         print(i)
            # time.sleep(0.5)
    # target函数的名字
    # args参数,必须使用元组传递
    # t1=threading.Thread(target=mission,args=(10,))
    # t2=threading.Thread(target=mission,args=(10,))
    #激活线程,不是执行线程,把当前线程任务加入到cpu的任务执行列表中
    等待cpu分配时间片来执行
    # t1.start()
    # t2.start()
    

    方式2

    # # class MyThread(threading.Thread):
    #     def __init__(self,end):
    #         self.end=end
    #         super().__init__()
    #     def run(self):
    #        for  i in range(self.end):
    #            print(i)
    # t1=MyThread(10)
    # t2=MyThread(10)
    # t1.run()------先执行完----任务顺序执行
    # t2.run()------后执行完----任务顺序执行
    # t1.start()-----将任务交给CPU,任务可以交替执行
    # t2.start()-----将任务交给CPU,任务可以交替执行
    

      当需要创建很多个执行相同方法的线程对象时,建议使用继承Thread类,重写run方法,run方法才是真正执行任务函数的方法。

    start方法和run方法有什么区别?

      start: 激活线程,不代表真正的执行,使得线程处于就绪状态,加入cpu执行任务列表。
      run:真正执行任务的函数。

    方式3

    线程池创建线程的两种方式:

      进程池下的线程池、第三方安装包threadpool。

    进程池下的线程池

    (1)multiprocessing.pool
      from multiprocessing.pool import ThreadPool

    同步apply
    异步
    # def work(i):
    #     print("第{}个线程开始".format(i))
    #     time.sleep(1)
    #
    # if __name__=="__main__":
    #     print("主程序执行开始")
    #     pool=ThreadPool(3)
    #     for i in range(3):
    #         pool.apply_async(work,args=(i,))
    #			args为一个元组,当为单个元素时,元素后面加“,”。
    #     pool.close()
    #     pool.join()
    #     print("主程序执行完毕")
    
    
    def sum2(b1,b2):
        pool = ThreadPool(3)
        for i in range(10):
            pool.apply_async(sum,args=(0,b1))
            pool.apply_async(sum,args=(0,b2))
    
        pool.close()
        pool.join()
    # if __name__=="__main__":
    #     start=time.time()
    #     # sum2(10000000,20000000)
    #     sum2(10,20)
    #     end=time.time()
    #     print("执行的时间{}".format(end-start))
    

    第三方安装包threadpool

      安装第三方包 pip install 包名
    import threadpool
      (1)引入threadpool模块。
      (2)定义线程函数。
      (3)创建线程池threadpool.ThreadPool(maxsize)。
      (4)创建需要线程池处理的任务列表
    requests= threadpool.makeRequests()。
      (5)将创建的多个任务put到线程池中。线程池对象.putRequests(任务)。
      (6)等到所有任务处理完毕。线程池对象.wait()----先用close再用join效果类似。

    makeRequests(任务,参数列表)
    参数列表:[((参数1,参数2),(字典型参数1,字典型参数2))]

    def work(i):
        print("第{}线程开始执行".format(i))
        time.sleep(1)
        print("第{}线程执行结束".format(i))
    
    # if __name__=="__main__":
    #     pool= threadpool.ThreadPool(5)
    #     requests=threadpool.makeRequests(work,args_list=range(3))
    #     for r in requests:
    #         pool.putRequest(r)  # 类似执行start
    #
    #     pool.wait()
    #     print("主程序执行完毕")
    
    
    def sum3(b1,b2):
        pool=threadpool.ThreadPool(5)
        asl=[((0,b1),None),((0,b2),None)]
        requests=threadpool.makeRequests(sum,args_list=asl)
        for i in requests:
            pool.putRequest(i)
        pool.wait()
    if __name__=="__main__":
        start=time.time()
        # sum3(10000000,20000000)
        sum3(10,20)
        end=time.time()
    print("执行的时间{}".format(end-start))
    
    

    四、线程的生命周期

      1. 新建:(人的出生): 创建线程对象,没有执行能力。
      2. 就绪:(等待就业): 调用了start方法,不是马上执行,把执行权利交给cpu。
      3. 运行:(入职工作): 执行线程的任务,获得了cpu的时间片,cpu在一个线程运行的时候,是可能将时间片分配给其他线程。
      4. 阻塞:(生病) : 处于等待的过程中(调用sleep),cpu不会将时间片分给阻塞状态的进程。
      5. 死亡:(死亡) :run方法执行完毕,run方法中抛出没有捕获的异常。

  • 相关阅读:
    键盘记录器,可截获到 QQ 的password
    《python源代码剖析》笔记 pythonm内存管理机制
    Unity 捕获IronPython脚本错误
    POJ 3020 Antenna Placement 最大匹配
    XCL-Charts画线图(Line Chart)
    android设置背景色为透明
    设计时属性文件
    Windows Mobile基础
    Wince 的CAB安装包
    惠普的 ipaq112 恢复出厂设置
  • 原文地址:https://www.cnblogs.com/wisteria68/p/13662488.html
Copyright © 2011-2022 走看看