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

    复习:
    队列
        队列 : 先进先出、数据进程安全
        管道 + 锁
        生产者消费者模型 : 解决数据供需不平衡
    管道
        双向通信 数据进程不安全
        EOFError:
            管道是由操作系统进行引用计数的,
            必须在所有进程中关闭管道后才能生成EOFError异常
    数据共享(不常用)
        Manager
        list dict 数据进程不安全的
    进程池
        存放进程的容器
        在进程创建之初,创建固定个数的进程
        会被多个任务循环利用
        节省了进程创建和销毁的时间开销
        降低了操作系统调度进程的压力
    信号量和进程池的区别
        信号量 n个任务开启n个进程,
              但同一时间只能有固定个数的进程在执行
              进程在等待被执行
        进程池 n个任务开启固定个数的进程
              因此同一时间只能有固定个数的进程在执行
              任务在等待被执行
    import time
    from multiprocessing import Pool
    def wahaha(i):
        time.sleep(1)
        print('*'*i)
    if  __name__ == "__main__":
        p  =  Pool(5)
        p.map(func=wahaha,iterable=range(10))
        自带close和join
        但是参数必须是一个iterable
        不能获取返回值
    
        res_l = []
        for i in range(10):
            res= p.apply_async(func = wahaha,args=[i,])
            res_l.append(res)
        for i in res_l:print(i.get())
        p.close() # 不能再提交新的任务
        p.join()  # 等待池中的任务都执行完
    主进程默认等待子进程结束 —— 守护进程
    普通的进程 : 根据你调用的函数执行结束它就结束了
    进程池里的进程
        没有返回值
            在提交任务之后:
            p.close() # 不能再提交新的任务
            p.join()  # 等待池中的任务都执行完
        有返回值的时候:
            在提交任务之后:
            for i in res_l:print(i.get())
    回调函数
        回调函数在什么时候执行
            子进程的任务执行完毕之后立即触发
        回调函数的参数
            子进程的返回值
        回调函数是由谁执行的
            主进程执行的
        在哪儿用?
            爬虫 :
                如果要爬取多个格式相同的网页
                真正影响程序效率的是网络的延迟
                计算 分析 处理网页的时间是很快的
    
    500
        有回调函数
        没有回调函数快
    进程
    操作系统管理进程
    进程是执行任务
    资源的隔离
    在一个操作系统中 同一时间 有多个任务
    多个任务之间的内存必须隔离开
    使用qq的时候 还能使用微信
    
    并发的要求日益增加
    聊天 —— 开子进程
    你可以看电影 —— 开子进程
    缓存其他电影
    
    开启一个子进程的开销 是很大的
    操作系统在进程之间的切换 时间开销也很大
    
    进程之间的通信
    数据共享 : 时间开销
    如果多个子进程之间的数据共享量过多的时候,
    就不应该将这些数据隔离开
    
    一个进程 —— 实现不了并发
    你既不希望数据隔离,还要实现并发的效果
    线程
    
    线程是轻量级的进程
    线程的创建和销毁所需要的时间开销都非常小
    线程直接使用进程的内存
    线程不能独立存在,要依赖于进程
    
    进程 —— 资源分配的最小单位
    线程 —— CPU调度的最小单位
        轻型进程 : 创建、销毁、切换 开销比进程小
        数据不隔离
        可以并发
        依赖进程
    每一个进程里至少有一个线程
    进程负责管理资源、线程负责执行代码
    def func(exp):
        # 2+3*5-6
        return eval(exp)
    
    
    
    python程序运行起来 —— 进程
    进程 —— 管理整个程序的内存,
             存储全局的变量 : 内置的函数 全局的名字
    线程 —— 执行代码
    
    多个线程 —— 同时执行 —— 并发效果
    利用python开启多线程 —— 并发
    import os
    import time
    from threading import Thread
    from multiprocessing import Process
    def func(i):
        print('-->',os.getpid())
        time.sleep(1)
        print('*'*i)
    
    if __name__ == '__main__':
        print(os.getpid())
        start = time.time()
        thread_lst = []
        for i in range(20):
            t = Thread(target=func,args=(i,))
            t.start()
            print('-->',t.name,t.ident)
            thread_lst.append(t)
        for t in thread_lst:t.join()
        print(time.time()-start)
    
        start = time.time()
        process_lst = []
        for i in range(20):
            p  = Process(target=func,args=(i,))
            p.start()
            process_lst.append(p)
        for p in process_lst: p.join()
        print(time.time()-start)
    
    效率问题 : 线程快 进程慢
    同一个进程下的多个线程进程号相同 : 线程号不同
    if __name__ == '__main__' : 开启进程 必须有这句话 但是开启线程不需要
        这种现象只在windows操作系统上才出现
    数据的共享问题:在进程之间数据隔离,在线程之间数据共享
    
    def manager():
        global n
        n = 0
    
    from threading import Thread
    n = 100
    t = Thread(target=manager)
    t.start()
    t.join()
    print('--->',n)
    
    
    python代码 --> 字节码 ——> 机器码
    c语言 java c++
    字节码 --> 机器码
    
    python 代码的计算效率 —— 高计算性
    python
    高IO型的程序 : web网站 爬虫
    
    python的程序就不能充分的利用CPU了呢???
    多进程 —— 开启和销毁的时候慢 操作系统切换的时候慢
    
    GIL —— 全局解释器锁
    锁线程 :在计算的时候 同一时刻只能有一个线程访问CPU
    线程锁限制了你对CPU的使用,但是不影响web类或者爬虫类代码的效率
    我们可以通过启动多进程的形式来弥补这个问题
    
    买电脑的时候
    4核8线程
        4核 —— 4个CPU  —— 4个
        4核8线程 -- 4个cpu -- 8个线程可以同时在cpu上运行的效果
        8核的
    
    
    守护线程
    import time
    from threading import Thread
    def func1():       # 守护线程
        while True:
            time.sleep(1)
            print('子线程')
    
    def func2():
        time.sleep(5)
        print('子线程2')
    
    t = Thread(target=func1)
    t2 = Thread(target=func2)
    t.setDaemon(True)
    t.start()
    t2.start()
    print('主线程')
    守护线程
    守护进程是等待主进程代码结束之后就结束
    守护线程是等待主线程都结束之后才结束
    cpu同一时刻只能执行一个进程中的线程 单线程的程序
    Thread实例对象的方法
      # isAlive(): 返回线程是否活动的。
      # getName(): 返回线程名。
      # setName(): 设置线程名。
    
    threading模块提供的一些方法:
      # threading.currentThread(): 返回当前的线程变量。
      # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后
    的线程。 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
      print(enumerate())  # 你启动的活着的线程数 + 1(主线程)
     print('-->',activeCount()) # 相当于len(enumerate())



    import time
    from threading import Thread,Lock
    def func(lock):
    global n
    lock.acquire()
    temp = n
    time.sleep(0.1)
    n = temp - 1
    lock.release()
    n = 100
    t_list = []
    lock = Lock()
    for i in range(100):
    t = Thread(target=func,args=[lock,])
    t.start()
    t_list.append(t)
    for t in t_list:t.join()
    print(n) #0

    同步锁(互斥锁)
    from threading import Lock

    lock= Lock() # 在同一个线程中
    # 能够被一个锁的多个acquire阻塞住了
    # 这种锁就叫做互斥锁
    lock.acquire()
    lock.acquire()


























  • 相关阅读:
    FCC学习笔记(二)
    FCC学习笔记(一)
    jQuery(三)
    jQuery(二)
    jQuery(一)
    JavaScript(九)
    JavaScript(八)
    2-1回归算法
    14-章小结
    13-模型训练及测试
  • 原文地址:https://www.cnblogs.com/Mr-Murray/p/9042766.html
Copyright © 2011-2022 走看看