看了这篇关于 GUI 情景中的 socket 编程的文章 http://www.jianshu.com/p/731a8359c2c5
然后仿照着按照自己的业务逻辑去做,出现了以下的问题。
现在有两个线程一个队列,一个线程负责入队,一个负责出队。 每个线程都是 1s 进行一次操作。 但是负责入队的线程经常会阻塞,就像阻塞了几秒,一下子入队好几次。
以下的代码都是关于队列cmd_q的
入队相关的代码
def send_heartbeat(self, receive_dic=None):
    # 转换为连接状态
    self.api_manager.socket_is_connect = True
    # 开始发送心跳
    self.heartbeat_thread = threading.Thread(target=self.__send_heartbeat_timer)
    self.heartbeat_thread.start()
def __send_heartbeat_timer(self):
    while self.api_manager.socket_is_connect:
        print("%s !!!!!!!!!!!!!put command  start!!!!!" % time.asctime(time.localtime(time.time())))
        self.api_manager.client.cmd_q.put(ClientCommand(ClientCommand.SEND, "heartbeat"))
        print("%s !!!!!!!!!!!!!put command  end!!!!!" % time.asctime(time.localtime(time.time())))
        logging.info("time: %s   send bearheart", time.asctime(time.localtime(time.time())))
        time.sleep(4) 
出队相关的代码
def run(self):
    while self.alive.isSet():
        try:
            # Queue.get with timeout to allow checking self.alive
            # print("%s !!!!!!!!!!!!!get command!!!!!" % time.asctime(time.localtime(time.time())))
            print("%s !!!!!!!!!!!!!get command  start!!!!!" % time.asctime(time.localtime(time.time())))
            cmd = self.cmd_q.get(True, 1)
            if (cmd.data == "heartbeat"):
                print("%s !!!!!!!!!!!!!get command  end!!!!!" % time.asctime(time.localtime(time.time())))
            handler = self.handlers[cmd.type]
            handler(cmd)
        except queue.Empty as e:
            continue
|  |      1justou      2016-12-23 18:27:13 +08:00 我看到入队代码有个 time.sleep(4) | 
|      6iceleaf      2016-12-26 00:51:15 +08:00 不知道你用的是什么 GUI 库,一般 GUI 库的线程问题,都应该结合 GUI 的对应 thread 函数来做,而不是直接启动 Python 的线程,这样才不会阻塞 GUI 的 event loop 例如 pyqt4 的: https://nikolak.com/pyqt-threading-tutorial/ | 
|  |      7toono OP @iceleaf 我用的就是 pyqt4, 我后来发现的确不是入队的问题。而是像你说的线程的问题。 我后来将程序改得简单粗暴,然后在周期性发送“ heartbeat ”的地方尝试使用了 QTimer 还是不能够解决问题了,也是在运行一段时间之后意外地阻塞一段时间。 | 
|      8iceleaf      2016-12-29 18:00:35 +08:00  1 @toono QTimer 利用了 Qt 的 event loop ,所以应该是不会阻塞界面的,但是 QTimer 到时间要执行的操作是一个耗时操作,这个会阻塞 QTimer 对象所在的线程,也就是主线程了,所以一般用 QThread 创建新的线程,然后在 run 函数中,创建 QTimer 的定时器,这样才不会阻塞主线程 | 
|  |      9whatcall      2016-12-30 22:10:49 +08:00 出队的 run()里面没有 sleep ,这样如果队列是空的(或者不是空的)不是一直在运行吗? CPU 占用会比较高吧,可以插一个 sleep |