我有用例,队列中包含UploadItem。队列必须是线程安全的。 UploadItem有一个方法canUpload()。 UploadItems被添加到尾部的队列中,但是peek()和poll()必须返回canUpload()为true的第一个UploadItem。这可能是头部的项目或更新的项目。基本上,我希望在准备好上传之前忽略项目,并且我希望队列返回准备好的最旧项目。
为了解决这个问题,我扩展了一个ConcurrentLinkedQueue,并且我已经覆盖了peek()和poll()。我已经同步了overriden方法,我正在使用迭代器来检索第一个有效项。
public class UploadQueue extends ConcurrentLinkedQueue<UploadItem> {
public UploadQueue() {}
@Override public synchronized UploadItem peek() {
for (UploadItem item : this) {
if (item.canUpload()) {
return item;
}
}
return null;
}
@Override public synchronized UploadItem poll() {
for (UploadItem item : this) {
if (item.canUpload()) {
remove(item);
return item;
}
}
return null;
}
}
这是一个很好的实现还是可以更高效地完成?使用迭代器检索项目是否有任何不利影响?我不能使用索引和get()来选择项目所以看来我必须使用迭代器。我也无法跟踪内部变量中的项目,因为它们是由外部函数链接和更改的。
这将在Android上运行,Android仍然使用Java 6.面对Lock-Free Concurrent Linked List in Java和ConcurrentLinkedQueue$Node remains in heap after remove(),是否存在某些Android手机可能仍有Java内存泄漏的风险?有人知道Java是否通常在Android上更新/修补(在其主要版本中)?
答案 0 :(得分:1)
这是一个很好的实现还是可以更高效地完成?
这两个标准并不相互排斥。
此外,在不知道canUpload
的成本如何,队列将获得多大以及条目保持“无法上传”状态多长时间的情况下,无法确定效率是否可能是一个问题。
但是,更有效地完成此操作肯定是可能。例如,如果您可以安排从“不可上载”到“可上载”的转换触发某种事件,那么您可以安排事件处理程序将UploadItem
添加到队列中。
对于UploadItem
对象集合的循环扫描可能比每次从队列开始扫描更有效。其他可能的策略也可能更好。
但是这些替代方法也可能会改变上传的顺序......如果这对你来说是个问题。
使用迭代器检索项目是否有任何不利影响?
ConcurrentLinkedQueue
的迭代器是weakly consistent。这意味着您无法保证看到迭代开始后添加的条目。对您的用例而言,这可能不是问题。 (如果下载偶尔会延迟到下一轮队列轮询,我觉得这很重要。)
这将在Android上运行,Android仍然使用Java 6.面对Lock-Free Concurrent Linked List in Java和ConcurrentLinkedQueue$Node remains in heap after remove(),是否存在某些Android手机可能仍有Java内存泄漏的风险?
这些问题并不表示长期记忆泄漏给我。如果有泄漏,看起来当线程丢弃迭代器时可能会被清除......或类似的东西。
另一方面,那些Q&amp; A是关于Oracle / OpenJDK Java而不是Apache Harvest / Android洁净室重新实现的。
是否有人知道Java是否通常在Android(主要版本)内更新/修补?
你无法概括。
首先,Java库的Android实现与标准Oracle / OpenJDK代码库的代码库不同。因此后者的更新/补丁不适用于前者。
其次,即使对标准的Android发行版进行更新/补丁,也不能保证1)手机制造商会接收它们,2)它们会打到电话公司的分销渠道,或3)个人智能手机用户将适用它们。
答案 1 :(得分:0)
使用PriorityQueue
与Comparator
首先在canUpload
进行比较,然后按相反顺序进行比较。