0

我想以线程安全的方式存储对象列表,同时保持优先级。最初我开始为此使用 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 有一些误解。

4

2 回答 2

1

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

这是用于BlockingQueue. 如果你需要这种阻塞行为,你可以使用它,否则你不需要。

BlockingQueue不保持任何优先级,严格先进先出。也许你正在使用PriorityBlockingQueue

来到你的伪代码:

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

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

  • 如果有多个线程被阻塞,哪个会先成功
  • 如果 athread X完成了putbefore athread Y那么thread X也将完成loggingbefore thread Y

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

void addToQueue(SomeObject obj) {
    synchronized (queue) {
        ... put it on my priority queue
        ... do some logging
    }
}
于 2013-10-21T21:01:49.720 回答
0

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

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

如果您想使用这种安全性来获得有序的日志记录,则必须将项目放入队列之前和从队列中取出项目之后进行记录。

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

于 2013-10-21T20:59:42.887 回答