java - 多个消费者从 ConcurrentLinkedQueue 轮询相同的值两次

标签 java multithreading

我广泛使用 ConcurrentLinkedQueue 进行多消耗任务排队,以前从未遇到过此问题。场景如下:

  1. 用一些任务填充我的队列
  2. 运行多个线程(在本例中为 2 个),这些线程将从队列中池化任务
  3. 当队列不为空时,从队列中池化并完成您的工作。

问题是,我的消费者将第一个元素池化了两次。为了避免混淆,我已经检查了队列中是否有重复的元素,但没有。到底是怎么回事?我不知道为什么,但同步 queue.poll() 并没有解决这个问题。如何解决这个问题?

我的队列轮询同步包装器(我以前不需要它,但这仍然没有帮助) 编辑:正如我所指出的,这没有帮助,但我必须尝试。提出正确的方法。

public class MultipleConsumerBlockingQueue<T> extends ConcurrentLinkedQueue<T> {
    private static final long serialVersionUID = 7994932568441881715L;
    private Logger log = LoggerFactory.getLogger(MultipleConsumerBlockingQueue.class);

    @Override
    public synchronized T poll() {
        T item = super.poll();
        return item;
    }

}

部分消耗线程

        @Override
        public void run() {
            try {
                AdvancedSearchAgent agent = new AdvancedSearchAgent();
                while ((dp = queue.poll()) != null) {
                    log.info("**** for publication dates: {} - {}", sdf.format(dp.getFromDate()), sdf.format(dp.getToDate()));
                    agent.searchByPublicationDate(dp.getFromDate(), dp.getToDate());
                    log.info("Expected results count {} on {} pages", agent.getResultsCount(), agent.getPagesCount());
                    iterateOverResult(agent, handler);
                }
            } catch (Exception ex) {
                log.error("Unhanded error occured ****. Exiting method *****", ex);
            }

        }

生成的输出:

08:05:15.171 [main] INFO  ****  - Generated 10 date intervals for querying
08:05:15.174 [main] INFO  ****  - Created inner task 1
08:05:15.174 [main] INFO  ****  - Created inner task 2
Czas wykonania= 0 sekund  0 godzin 0 minut 0 sekund
08:05:15.178 [pool-2-thread-1] INFO  **** - **** for publication dates: 01-02-2013 - 03-03-2013
08:05:15.178 [pool-2-thread-2] INFO  **** - ****  for publication dates: 01-02-2013 - 03-03-2013

编辑:

这是队列中项目的转储。没有重复。

   1# -> Wt 2013-01-01 : Cz 2013-01-31
   2# -> Pt 2013-02-01 : N 2013-03-03
   3# -> Pn 2013-03-04 : Śr 2013-04-03
   4# -> Cz 2013-04-04 : So 2013-05-04
   5# -> N 2013-05-05 : Wt 2013-06-04
   6# -> Śr 2013-06-05 : Pt 2013-07-05
   7# -> So 2013-07-06 : Pn 2013-08-05
   8# -> Wt 2013-08-06 : Cz 2013-09-05
   9# -> Pt 2013-09-06 : N 2013-10-06
  10# -> Pn 2013-10-07 : Pt 2013-10-11

最佳答案

我有一个常见的错误 - 它涉及日期格式的 NonThreadSafety。从队列轮询很好,只生成有错误的日志。 sdf 是worker共享的SimpleDateFormat对象(一开始它应该只是单线程所以没人关心)。由于它不是线程安全的,因此格式化了错误的日期。很遗憾我之前没有意识到这一点。 感谢大家的评论和指出。

关于java - 多个消费者从 ConcurrentLinkedQueue 轮询相同的值两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19311527/

相关文章:

java - 来自具有多个参数的构造函数的类的线程

c# - WPF UI 多任务处理

java - 为什么我的 Java 代码会导致 netbeans 卡住

java - 在应用程序编译中 - Java

java - 如何禁用Ctrl+P,使用户无法直接打印当前打开的文档?

java - 没有 Collections.synchronized 的线程安全 LinkedHashMap

c++ - 客户端断开连接后处理服务器应用程序中的线程

java.sql.timestamp 与日期

Java Swing - 制作两个 JLists "siblings"- 即只能选择其中一个项目

c - VS2010 - C - process.h - "joining"线程以 _beginthread 开始