【问题标题】:Queue with timeout that removes not retrieved objects删除未检索到的对象的超时队列
【发布时间】:2014-02-06 20:15:41
【问题描述】:

我有线程向套接字写入一些内容,然后开始等待响应。该线程需要在给定的时间内检索响应,例如 100 毫秒。 我的想法是创建读取器线程,该线程将从套接字读取并将响应存储在阻塞队列中。当阅读器完成工作并将对象放入队列时,第一个线程只是等待。如果读者在一段时间内一切正常,如果读者不这样做,我想抛出异常,它也可以。问题是当我在 TimeOutException 之后出现时,由于超时而没有从队列中取出的对象仍然存在,甚至可能刚刚准备好插入队列中。我只想要下一个对象。我应该如何跳过这条消息?或者可能有更好的方法来解决这个问题?

另外,连接是保持活动的,所以套接字超时是不合适的。

【问题讨论】:

  • 据我所知,套接字超时只是一个告诉您读取阻塞时间过长的事件。可以忽略这个超时事件,继续阅读:socket连接没有改变。你试过这个吗?
  • "这个线程需要在给定的时间内获取响应,例如100毫秒。" 当读取超时时程序应该怎么做?

标签: java multithreading sockets concurrency timeout


【解决方案1】:

我会将BlockingQueue 子类化以覆盖poll()offer() 方法,这只是调用super.poll()super.offer()。它会在提供新项目时添加时间戳,并在轮询时丢弃任何在队列中时间过长的项目。比如:

public class TimedItemBlockingQueue<T> extends ArrayBlockingQueue<TimedItem<T>> {
    private class TimedItem<T> {
        T data;
        long timestamp;
        TimedItem<T>(T data) {
            this.data = data;
            this.timeStamp = <get_tiemstamp>
    }

    T poll() {
        TimedItem<T> item = super.poll();
        if (isValid(item.timestamp)) {
            return item.data;
        }
        /* Plus extra code to handle exceptions and other cases */
    }

    boolean offer(T data) {
        TimedItem<T> item = new TimedItem<T>(data);
        return super.offer(item);
}

您可能需要覆盖所有 poll() 方法。

在这种情况下,第一个线程只会调用poll(),甚至不知道中间是否有这样的队列或有多少对象“过期”

【讨论】:

    【解决方案2】:

    最好的方法是让发件人包含一个时间戳(或者如果不可能,读者可以包含一个时间戳)当您从队列中收到消息时,您检查时间戳,如果没有足够的时间,您假设它已经计时出(或将出)

    如果您需要让调用队列的代码透明,您可以创建一个丢弃旧消息的 Queue 子类。

    【讨论】:

      猜你喜欢
      • 2011-07-20
      • 2014-03-29
      • 1970-01-01
      • 2012-07-27
      • 2020-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多