zoukankan      html  css  js  c++  java
  • 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请求/数据库请求等;而对于计算密集型任务,应该使用多进程

  • 相关阅读:
    网络七层
    微信小程序开发工具 常用快捷键
    BZOJ 1026 windy数 (数位DP)
    BZOJ 1026 windy数 (数位DP)
    CodeForces 55D Beautiful numbers (SPOJ JZPEXT 数位DP)
    CodeForces 55D Beautiful numbers (SPOJ JZPEXT 数位DP)
    HDU 3709 Balanced Number (数位DP)
    HDU 3709 Balanced Number (数位DP)
    UVA 11361 Investigating Div-Sum Property (数位DP)
    UVA 11361 Investigating Div-Sum Property (数位DP)
  • 原文地址:https://www.cnblogs.com/zhaop8078/p/11359792.html
Copyright © 2011-2022 走看看