• thread.event说明


    Python中的threading.Event()操控多线程的过程有:
    - 定义事件:man_talk_event = threading.Event()
    - 创建线程,传入对应事件:t1 = threading.Thread(target=man, args=(man_talk_event,), name='man')
    - 查看对应事件的标志:man_talk_event.is_set()返回Ture或False
    - 阻塞对应事件线程:man_talk_event.wait() 如果事件标志为True则不阻塞
    - 继续对应事件线程:man_talk_event.set() 设置事件标志为True
    - 结束对应事件线程:man_talk_event.clear() 设置事件标志为False
    - 注意创建线程的时候,如果之前设置成t1.setDaemon(True),则不会阻塞主线程

    threading.Event机制类似于一个线程向其它多个线程发号施令的模式,其它线程都会持有一个threading.Event的对象,这些线程都会等待这个事件的“发生”,如果此事件一直不发生,那么这些线程将会阻塞,直至事件的“发生”。

    对此,我们可以考虑一种应用场景(仅仅作为说明),例如,我们有多个线程从rabbitmq队列中读取数据来处理,这些线程都要尝试去连接rabbitmq的服务,一般情况下,如果Redis连接不成功,在各个线程的代码中,都会去尝试重新连接。如果我们想要在启动时确保rabbitmq服务正常,才让那些工作线程去连接Redis服务器,那么我们就可以采用threading.Event机制来协调各个工作线程的连接操作:主线程中会去尝试连接rabbitmq服务,如果正常的话,触发事件,各工作线程会尝试连接rabbitmq服务。

    1、日志的配置文件log/test.log

    [log]
    name = 'nova'
    # support notset debug info warning error critical
    level= debug
    log_file = E:workspacedjango_flowlog	est.log
    

     

    2、方便使用log日志,写一个函数接口给其他人方便调用log/log.py

    # author:wanstack
    import logging
    import configparser
    
    
    def log(name,level,log_file):
        # 创建一个logger对象
        logger = logging.getLogger(name)
        # 设置日志级别
        log_level = getattr(logging,level.upper())
        logger.setLevel(log_level)
        # 创建format日志格式
        formatter = logging.Formatter('%(asctime)s -- %(name)s -- %(levelname)s -- %(message)s')
        # 创建输出流
        fn = logging.FileHandler(log_file)
        # 添加formatter日志格式到输出流中
        fn.setFormatter(formatter)
        # 创建filter,并作用在输出流上
        filter = logging.Filter(name)
        fn.addFilter(filter)
        # 将logger对象关联到输出流上
        logger.addHandler(fn)
        return logger
    
    # if __name__ == '__main__':
    #     cf = configparser.ConfigParser()
    #     cf.read('log.conf')
    #     name = cf.get('log', 'name')
    #     level = cf.get('log', 'level')
    #     log_file = cf.get('log', 'log_file')
    #     logger = log(name,level,log_file)
    

      

    3、连接rabbitmq,如果连接不上就一直发日志,如果连接上了就退出other/test.py

    # author:wanstack
    import pika
    import socket
    import threading
    import time
    from log.log import log
    import configparser
    import os
    RabbitmqHost = '172.20.6.184'
    RabbitmqPort = 5672
    RabbitmqUser = 'admin'
    RabbitmqPwd = 'admin'
    
    
    def check_rabbitmq_port(RabbitmqHost,RabbitmqPort):
        """
        检查rabbitmq端口是否存活
        :param RabbitmqHost: 
        :param RabbitmqPort: 
        :return:  如果存活返回true,否则返回None
        """
        # AF_INET ipv4
        # SOCK_STREAM TCP
        sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        # 设置超时时间
        sock.settimeout(1)
        try:
            sock.connect((RabbitmqHost,RabbitmqPort))
            return True
        except Exception:
            logger.error('Server port {RabbitmqPort} not connect!'.format(RabbitmqPort=RabbitmqPort))
        sock.close()
    
    
    def worker(event):
        # 查看对应事件的标志,返回Ture或False
        while not event.is_set():
            logger.debug('Waiting for rabbitmq redy')
            """
            我们在工作线程中加入了一个while循环,直到rabbitmq_ready事件触发之后才会结束循环,
            wait方法调用会在1秒的超时后返回,这样,
            我们就可以看到各个工作线程在系统启动的时候等待redis_ready的同时,
            会记录一些状态信息。以下是这个程序的运行结果
            """
            event.wait(1)
        # 当事件标志为true时,才执行下面的内容,否则一直阻塞在event.wait上
        logger.debug('rabbitmq ready, and connect to rabbitmq server and do some work [%s]', time.ctime())
        credentials = pika.PlainCredentials(RabbitmqUser,RabbitmqPwd)
        connection = pika.BlockingConnection(pika.ConnectionParameters(host=RabbitmqHost,credentials=credentials))
    
    
    if __name__ == "__main__":
        # 解析log配置文件,获取logger对象
        cf = configparser.ConfigParser()
        BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
        log_conf = os.path.join(BASE_DIR,'loglog.conf')
        cf.read(log_conf)
        name = cf.get('log', 'name')
        level = cf.get('log', 'level')
        log_file = cf.get('log', 'log_file')
        logger = log(name,level,log_file)
        rabbitmq_ready = threading.Event()
        t1 = threading.Thread(target=worker,args=(rabbitmq_ready,),name='t1')
        t1.start()
        t2 = threading.Thread(target=worker,args=(rabbitmq_ready,),name='t2')
        t2.start()
        logger.debug('first of all, check rabbitmq server, make sure it is OK, and then trigger the rabbitmq ready event')
    
        # 检测rabbitmq-server端口是否存活
        check_port = check_rabbitmq_port(RabbitmqHost, RabbitmqPort)
        if check_port:
            rabbitmq_ready.set()
    
  • 相关阅读:
    Codeforces Round #702 (Div. 3) 题解
    Educational Codeforces Round 104 (Rated for Div. 2) A~E题解
    AtCoder Regular Contest 112 A~D题解
    Codeforces Round #701 (Div. 2) A~E 题解
    java String, StringBuffer, StringBuilder简单介绍和使用
    货仓选址
    线程的同步
    数据结构课设作业
    线程的生命周期(java 图)
    JAVA多线程的创建和使用
  • 原文地址:https://www.cnblogs.com/wanstack/p/9043281.html
Copyright © 2020-2023  润新知