我希望以线程安全的方式存储对象列表,同时保持优先级。最初我开始使用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有一些误解。
答案 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 X
在put
之前完成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
来获取有序日志记录。多线程意味着并行执行,这意味着某些操作没有排序。日志记录可以有一个时间戳,并以错误的顺序查看它们,即在控制台中,对我来说看起来像一个小故障,不值得牺牲并行执行的优势。