【问题标题】:How to implement a shared buffer between Java threads?如何在 Java 线程之间实现共享缓冲区?
【发布时间】:2012-08-14 05:21:30
【问题描述】:

我打算在生产者和消费者线程之间编写一个共享缓冲区。这是我的代码:

class PQueue
{
    Token token;
    boolean flag = false;   // false: add, true: poll

    PQueue()
    {
        token = null;
    }

    synchronized void add(Token token)
    {
        if(flag == true)
        {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        flag = true;
        notify();
        this.token = token;
    }

    synchronized Token poll()
    {
        if(flag == false)
        {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        flag = false;
        notify();
        return this.token;
    }
}

我是多线程的新手。是否有任何潜在的并发错误?这是实现这一目标的“标准/通用”方式吗?或者有没有更简单、更有效的方法?

【问题讨论】:

  • 你不能只使用 java.util.concurrent.BlockingQueue 吗?
  • notify() 在同步块中对我来说看起来很可疑(但不知道这是否有效或导致死锁)
  • @Andreas_D:你不能用其他方式打电话给notify(),你是什么意思可疑? (他的代码因其他原因而可疑,但不是那个原因。)
  • @vanza 这是一个很好的建议。就我而言,我只需要一个元素缓冲区。 BlockingQueue 有类似的实现吗?
  • @vanza - google 上的一次快速浏览提醒我你是对的。 notify 必须在同步块内调用。

标签: java multithreading shared producer-consumer


【解决方案1】:

看看java.util.concurrent 包,特别是BlockingQueue 接口和实现它的类。这些用于将消息从一个线程传递到另一个线程。 SynchronousQueue 正是您想要实现的。

您自己的实现存在一些缺陷。一方面,两个共享变量都应声明为volatile,以确保一个线程上的更改被另一个线程看到。而你的if (flag == false)if (flag == true) 测试实际上应该是while 循环,因为wait() 可以在notify() 实际上没有被调用时wake up spuriously

我建议不要使用单独的标志变量,而是将标记设置为 null 以指示没有对象。我建议不要在InterruptedException 面前捕获、打印和盲目地继续,而是让这两种方法在发生异常时抛出该异常。这些是阻塞方法,调用者有责任处理阻塞方法被中断的可能性。

另外,我不知道您的 Token 类是什么,但您的队列中没有任何内容实际上取决于它的类型。定义一个通用的PQueue<T> 会更有意义,然后如果你想传递令牌则使用PQueue<Token>

【讨论】:

    【解决方案2】:

    1.尝试使用java.util.concurrent包中的thread-safe类和接口。

    2. 使用BlockingQueue InterfaceArrayBlockingQueue Class

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-01
      • 2011-05-22
      • 1970-01-01
      • 1970-01-01
      • 2016-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多