我是否需要同步对BlockingQueue(java)的调用?
我希望以线程安全的方式存储对象列表,同时保持优先级。最初,我使用BlockingQueue进行此操作,因为它是线程安全的,并且能够维护自定义优先级 我想知道我是否需要同步我的方法?我的代码如下所示:我是否需要同步对BlockingQueue(java)的调用?,java,multithreading,synchronized,blockingqueue,Java,Multithreading,Synchronized,Blockingqueue,我希望以线程安全的方式存储对象列表,同时保持优先级。最初,我使用BlockingQueue进行此操作,因为它是线程安全的,并且能够维护自定义优先级 我想知道我是否需要同步我的方法?我的代码如下所示: void addToQueue(SomeObject obj) { ... put it on my priority queue ... do some logging } 我注意到,当从多个线程访问addToQueue时,日志记录是无序的。所以我把我的方法包装成这样: void
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之前,线程中的操作发生在另一个线程中从BlockingQueue访问或移除该元素之后的操作之前
如果您想使用该安全机制来获得有序的日志记录,则必须在将项目放入队列之前以及从队列中取出项目之后进行日志记录
我不会使用synchronized
来获得有序的日志记录。多线程意味着并行执行,这意味着某些操作没有顺序。日志记录可能有一个时间戳,并且在控制台中以错误的顺序查看它们,这对我来说似乎是一个小故障,不值得牺牲并行执行的优势
一种队列,它还支持在检索元素时等待队列变为非空,在存储元素时等待队列中的空间变为可用的操作
这是的javadoc。如果需要这种阻塞行为,可以使用它,否则就不需要
阻塞队列
不保持任何优先级,严格来说它是先进先出的。也许您正在使用
来到您的伪代码:
void addToQueue(SomeObject obj) {
... put it on my priority queue
... do some logging
}
队列是线程安全的,但这只意味着多个线程可以同时调用并将其放在我的优先级队列上,而不会造成任何数据损坏。它不保证以下任何一项:
- 如果有多个线程被阻塞,哪个线程将首先成功
- 如果
线程X
在线程Y
之前完成放置,则线程X
也将在线程Y
之前完成日志记录
如果您需要所有的addToQueue
在不与其他线程交叉的情况下发生,那么您需要同步。请注意,您可以使用队列对象本身:
void addToQueue(SomeObject obj) {
synchronized (queue) {
... put it on my priority queue
... do some logging
}
}
BlockingQueue
中唯一同步的东西是各个方法中代码的一部分。日志记录不是BlockingQueue
的一部分,因此与它的执行无关。这是一个对象还是一个集合?除非在实现中另有规定,否则批量收集操作addAll、containsAll、retainal和removeAll不一定以原子方式执行。因此,例如,addAll(c)在只添加c中的一些元素之后失败(引发异常)是可能的。BlockingQueue本质上具有阻塞操作,因此在同步代码段内进行阻塞调用时要小心,否则可能会导致死锁。