【问题标题】:Multiple Consumer Threads Consume Queue FIFO Overall多个消费者线程整体消耗队列FIFO
【发布时间】:2019-06-10 05:06:53
【问题描述】:

当我尝试学习 JAVA 编程的多线程部分时,在处理 One Producer - Multiple Consumer 编码时遇到以下问题。

我想要实现的是:多个消费者线程按照它们被放入队列的顺序将它们从队列中取出。也就是说,让消费者线程整体保持先进先出的方式。

final BlockingDeque<String> deque = new LinkedBlockingDeque<String>();

Runnable rb = new Runnable() {
    public void run() {
        try {
            System.out.println(deque.takeLast());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
};

deque.putFirst("a");
deque.putFirst("b");
deque.putFirst("c");
deque.putFirst("d");

ExecutorService pool = Executors.newFixedThreadPool(4);
pool.submit(rb);
pool.submit(rb);
pool.submit(rb);
pool.submit(rb);

我在寻找什么: 一个 b C d

实际输出: b C 一个 d

OR 随机顺序

任何简单的解决方案来解决这个问题?谢谢!

【问题讨论】:

  • 需要同步输出synchronized (deque) { try { System.out.println(deque.takeLast()); } catch (InterruptedException e) { e.printStackTrace(); } }

标签: java multithreading fifo


【解决方案1】:

在你的情况下,问题是

System.out.println(deque.takeLast());

实际上是两条指令,它们一起不是原子的。想象这样的场景:

  1. 线程 1 从队列中获取字符串。
  2. 线程 2 从队列中获取字符串。
  3. 线程 2 打印值。
  4. 线程 1 打印值。

所以这完全取决于操作系统将如何管理线程执行。

在您的情况下,一种可能的解决方案是将 synchronized 关键字添加到 run 方法:

Runnable rb = new Runnable() {
    public synchronized void run() {
         try {
              String s = deque.takeLast();
              System.out.println(s);
         } catch (InterruptedException e) {
              e.printStackTrace();
         }
    }
};

这将同步您在此处创建的匿名类的实例。由于您将相同的可运行文件传递给 ExecutorService - 它应该可以工作。 或者,您可以在 queue 对象上同步,因为您的可访问队列对象的可运行对象将在许多线程中执行,因为您将其传递给 ExecutorService

Runnable rb = new Runnable() {
    public void run() {
        synchronized (deque) {
             try {
                 String s = deque.takeLast();
                 System.out.println(s);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
        }
    }
};

还要记住关闭你的线程池,因为现在你的应用程序永远不会退出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 2021-11-14
    • 2017-11-17
    • 1970-01-01
    相关资源
    最近更新 更多