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方法中抛出没有捕获的异常。

  • 相关阅读:
    使用 requests 维持会话
    使用 requests 发送 POST 请求
    使用 requests 发送 GET 请求
    requests 安装
    使用 urllib 分析 Robots 协议
    使用 urllib 解析 URL 链接
    使用 urllib 处理 HTTP 异常
    使用 urllib 处理 Cookies 信息
    使用 urllib 设置代理服务
    按单生产程序发布
  • 原文地址:https://www.cnblogs.com/wisteria68/p/13662488.html
Copyright © 2011-2022 走看看