• python3-多线程


    多线程简介
    线程(Thread)也称轻量级进程,时操作系统能够进行运算调度的最小单位,它被包涵在进程之中,时进程中的实际运作单位。线程自身不拥有资源,只拥有一些在运行中必不可少的资源,但他可与同属一个进程的其他线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一进程中的多个线程之间可以并发执行。
    线程有就绪/阻塞/运行三种基本状态:
      1/ 就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机
      2 / 运行状态是指线程占有处理机正在运行。
      3/ 阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行

    结论:在python中,对于计算密集型任务,多进程占优势;对于I/O密集型任务,多线程占优势

    python多线程其它介绍

    1/1 多线程threading模块
    方法一 创建threading.Thread类的实例,调用其start()方法
    方法二 继承Thread类,在子类中重写run()和init()方法


    1/2 多线程同步Lock(互诉锁)
    #如果多个线程共同对某个数据修改,则可能出现不可预料的结果,这个时候就需要使用互诉锁来进行同步
    #调用锁
    lock = threading.Lock()
    #获取锁,用户线程同步
    lock.acquire()

    1/3 多线程同步Semaphore(信号量)
    互诉锁是只允许一个线程访问共享数据,而信号量是同时允许一定数量的线程访问共享数据
    semaphore = threading.BoundedSemaphore()

    练习:
    import threading
    import time

    semaphore = threading.BoundedSemaphore(5)

    def yewubanli(name):
    semaphore.acquire()
    time.sleep(3)
    print(f"{time.strftime('%Y-%m-%d %H:%M:%S')} {name} 正在办理业务")

    semaphore.release()


    thread_list = []
    for i in range(12):
    t = threading.Thread(target=yewubanli, args=(i,))
    thread_list.append(t)

    for thread in thread_list:
    thread.start()

    for thread in thread_list:
    thread.join()

    1/4 多线程同步Condition
    条件对象Condition能让一个线程A停下来,等待其它线程B,线程B满足了某个条件后通知(notify)线程A继续运行。线程首先获取一个条件变量锁,如果条件不足,则该线程等待(wait)并释放条件变量锁;如果条件满足,就继续执行线程,执行完成后可以通知(notify)其它状态为wait的线程执行。其它处于wait状态的线程接到通知后会重新判断条件以确定是否继续执行。
    cond = threading.Condition()

    1/5 多线程同步Event
    事件用于线程之间的通信。一个线程发出一个信号,其它一个或多个线程等待,调用Event对象的wait方法,线程则会阻塞等待,直到别的线程set之后才会被唤醒
    cond = threading.Event()


    1/6 线程优先级队列(queue)
    Python的queue模块中提供了同步的/线程安全的队列类,包括先进先出队列Queue/后进后出队列LifoQueue和优先级队列PriorityQueue。这些队列都实现了锁原语,可以直接使用来实现线程之间的同步。

    练习:
    import threading, time
    import queue


    q = queue.Queue(maxsize=5)

    def ProducerA():
    count = 1
    while True:
    q.put(f"冷饮 {count}")
    print(f"{time.strftime('%H:%M:%S')} A 放入:[冷饮 {count}]")
    count += 1
    time.sleep(1)

    def ConsumerB():
    while True:
    print(f"{time.strftime('%H:%M:%S')} B 取出 [{q.get()}]")
    time.sleep(5)

    p = threading.Thread(target=ProducerA)
    c = threading.Thread(target=ConsumerB)

    c.start()
    p.start()


    1/7 多线程之线程池pool
    在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或其它更多资源。虚拟机也将视图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。同样的道理,多任务情况下每次都会生成一个新线程,执行任务后资源再被回收就显得非常低效,因此线程池就是解决这个问题的方法。类似的还有连接池/进程池等。
    将任务添加到线程池中,线程池会自动指定一个空闲的线程取执行任务,当超过线程池的最大线程数时,任务需要等待有新的空闲线程后才会被执行。
    我们可以使用threading模块及queue模块定制线程池,也可以使用multiprocessing。from multiprocessing import Pool这样导入的Pool表示的时进程池,from multiprocessing.dummy import Pool这样导入的Pool表示的时线程池

    练习:
    from multiprocessing.dummy import Pool as ThreadPool
    import time


    def fun(n):
    time.sleep(2)

    start = time.time()
    for i in range(5):
    fun(i)
    print("单线程顺序执行耗时:", time.time() - start)

    start2 = time.time()

    pool = ThreadPool(processes=5)
    results2 = pool.map(fun, range(5))
    pool.close()
    pool.join()
    print("线程池(5)并发执行耗时:",time.time() - start2)


    总结:
    Python多线程适合用再I/O密集型任务中。I/O密集型任务较小时间用再CPU计算上,较多时间用再I/O上,如文件读写/web请求/数据库请求等;而对于计算密集型任务,应该使用多进程

  • 相关阅读:
    php Windows系统 wamp集成环境下redis的使用
    IO流文件拷贝
    IO流框架
    Map集合
    泛型
    Deque(队列)
    List接口
    Iterator接口(迭代器)
    Java中的异常详解
    Java中的正则表达式
  • 原文地址:https://www.cnblogs.com/zhaop8078/p/11359792.html
Copyright © 2020-2023  润新知