zoukankan      html  css  js  c++  java
  • 信号量、Event、定时器

    一 信号量

    信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,信号量同一时间可以有5个任务拿到锁去执行,如果说互斥锁是合租房屋的人去抢一个厕所,那么信号量就相当于一群路人争抢公共厕所,公共厕所有多个坑位,这意味着同一时间可以有多个人上公共厕所,但公共厕所容纳的人数是一定的,这便是信号量的大小

    from threading import Thread, Semaphore, currentThread
    import time, random
    
    sm = Semaphore(5)    # 锁的个数
    
    
    def task():
        # sm.acquire()
        # print("%s in " % currentThread().getName())
        # sm.release()       # 简写为以下形式
        with sm:
            print("%s in " % currentThread().getName())
            time.sleep(random.randint(1, 3))
    
    
    if __name__ == "__main__":
        for i in range(10):     # 10个人去抢
            t = Thread(target=task)
            t.start()

    解析

    Semaphore管理一个内置的计数器,
    每当调用acquire()时内置计数器-1;
    调用release() 时内置计数器+1;
    计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。
    

    二 Event

    线程的一个关键特性是每个线程都是独立运行且状态不可预测。如果程序中的其他线程需要通过判断某个线程的状态来确定自己下一步的操作,这时线程同步问题就会变得非常棘手。为了解决这些问题,我们需要使用threading库中的Event对象。 对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。在初始情况下,Event对象中的信号标志被设置为假。如果有线程等待一个Event对象, 而这个Event对象的标志为假,那么这个线程将会被一直阻塞直至该标志为真。一个线程如果将一个Event对象的信号标志设置为真,它将唤醒所有等待这个Event对象的线程。如果一个线程等待一个已经被设置为真的Event对象,那么它将忽略这个事件, 继续执行

    from threading import Event
    
    event.isSet():返回event的状态值;
    
    event.wait():如果 event.isSet()==False将阻塞线程;
    
    event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;
    
    event.clear():恢复event的状态值为False。
    

    例如,有多个工作线程尝试链接MySQL,我们想要在链接前确保MySQL服务正常才让那些工作线程去连接MySQL服务器,如果连接不成功,都会去尝试重新连接。那么我们就可以采用threading.Event机制来协调各个工作线程的连接操作

    from threading import Thread, Event
    import time
    
    event = Event()
    # event.wait()   # 在此等着
    # event.set()    # 等待结束
    
    def student(name):
        print("学生%s正在听课" % name)
        event.wait(2)    # 可以设置超时时间,即使没有接收到set的信号,也可以继续往后进行
        print("学生%s正在课件活动" % name)
    
    
    def teacher(name):
        print("%s正在上课" % name)
        time.sleep(7)
        event.set()
    
    
    if __name__ == "__main__":
        stu1 = Thread(target=student, args=("alex",))
        stu2 = Thread(target=student, args=("black",))
        stu3 = Thread(target=student, args=("jack",))
        t1 = Thread(target=teacher, args=("nico",))
    
        stu1.start()
        stu2.start()
        stu3.start()
        t1.start()

    ftp中

    from threading import Thread, Event, currentThread
    import time
    
    event = Event()
    
    
    def conn():    # 连接服务端
        n = 0
        while not event.is_set():
            if n == 3:
                print("%s try too many times" % currentThread().getName())
                return
            print("%s try %s" % (currentThread().getName(), n))
            event.wait(0.5)   # 超时时间
        print("%s is connected" % currentThread().getName())
    
    
    def check():   #  检测服务端是否正常进行
        print("%s is checking" % currentThread().getName())
        time.sleep(5)
        event.set()
    
    
    if __name__ == "__main__":
        for i in range(3):
            t = Thread(target=conn)
            t.start()
        t = Thread(target=check)
        t.start()

    三 定时器

    定时器,指定n秒后执行某操作

    from threading import Timer
    
    def task(name):
        print("hello %s" % name)
    
    t = Timer(5,task,args=("alex", ))    # 5s后
    t.start()
    

      

    验证码

    # 验证码
    from threading import Timer
    import random
    
    class Code:
        def __init__(self):
            self.make_cache()
    
        def make_cache(self, interval=5):
            self.cache = self.make_code()
            print(self.cache)
            self.t = Timer(interval, self.make_cache)
            self.t.start()
    
        def make_code(self, n=4):
            res = ""
            for i in range(n):
                s1 = str(random.randint(0, 9))
                s2 = chr(random.randint(65, 90))     # 字母
                res += random.choice([s1, s2])
            return res
    
        def check(self):
            while True:
                code = input("请输入验证码:").strip()
                if code.upper() == self.cache:
                    print("验证码正确")
                    self.t.cancel()
                    break
    
    obj = Code()
    obj.check()
    

      

     
  • 相关阅读:
    spring事物管理五种配置方式
    解决html中内部元素mouse事件干扰
    普通类获取ApplicationContext(附带servletContext)的方法
    SQL学习基础知识
    vs 工具技巧手册
    wcf client与webservice通信备注
    BackgroundWorker学习一
    silverlight发布注意事项
    将wcf 以webservice的方式调用
    Visual Studio 2005 Team Foundation Server (TFS)单服务器安装记
  • 原文地址:https://www.cnblogs.com/fantsaymwq/p/10133455.html
Copyright © 2011-2022 走看看