我需要将我的调用同步到BlockingQueue(java)吗?

时间:2013-10-21 20:42:28

标签: java multithreading synchronized blockingqueue

我希望以线程安全的方式存储对象列表,同时保持优先级。最初我开始使用BlockingQueue,因为它的线程安全并且能够保持自定义优先级。

我想知道我是否需要同步我的方法?我的代码如下:

void addToQueue(SomeObject obj) {
    ... put it on my priority queue
    ... do some logging
}

我注意到当从多个线程访问addToQueue时,日志记录发生故障。所以我把方法包装成这样:

void addToQueue(SomeObject obj) {
    syncronized(myMutex) {
        ... put it on my priority queue
        ... do some logging
    }
}

这似乎使记录保持有序。所以现在我得出的结论是,如果我要走这条路线,那么也许我的代码通过不使用BlockingQueue会更高效,而是使用Set或List并自己管理优先级。

也许我对BlockingQueue有一些误解。

2 个答案:

答案 0 :(得分:1)

  

一个队列,它还支持在检索元素时等待队列变为非空的操作,并在存储元素时等待队列中的空间可用。

这是BlockingQueue的javadoc。如果你需要这种阻止行为,你可以使用它,否则你不需要。

BlockingQueue 维持任何优先级,严格来说是先进先出。也许你正在使用PriorityBlockingQueue?< / p>

来到你的伪代码:

void addToQueue(SomeObject obj) {
    ... put it on my priority queue
    ... do some logging
}

队列是线程安全的,但这只意味着多个线程可以同时调用put it on my priority queue而没有任何数据损坏。它不保证以下任何一项:

  • 如果有多个线程被阻止哪个线程将首先成功
  • 如果thread Xput之前完成thread Y,那么thread X也将在logging之前完成thread Y

如果您需要在没有与其他线程交错的情况下发生所有addToQueue,则需要进行同步。请注意,您可以使用队列对象本身:

void addToQueue(SomeObject obj) {
    synchronized (queue) {
        ... put it on my priority queue
        ... do some logging
    }
}

答案 1 :(得分:0)

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html

  

与其他并发集合一样,在将对象放入BlockingQueue之前,线程中的操作发生在从另一个线程中的BlockingQueue访问或删除该元素之后的操作之前。

如果您想使用该安全性来获取有序日志记录,则必须在将项目放入队列之前记录,并在从队列中取出项目之后

。 >

我不会使用synchronized来获取有序日志记录。多线程意味着并行执行,这意味着某些操作没有排序。日志记录可以有一个时间戳,并以错误的顺序查看它们,即在控制台中,对我来说看起来像一个小故障,不值得牺牲并行执行的优势。