如果民意调查不一定返回第一项,那么ConcurrentLinkedQueue是一个不错的选择吗?

时间:2014-12-07 06:28:58

标签: java android multithreading concurrency queue

我有用例,队列中包含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 JavaConcurrentLinkedQueue$Node remains in heap after remove(),是否存在某些Android手机可能仍有Java内存泄漏的风险?有人知道Java是否通常在Android上更新/修补(在其主要版本中)?

2 个答案:

答案 0 :(得分:1)

  

这是一个很好的实现还是可以更高效地完成?

这两个标准并不相互排斥。

此外,在不知道canUpload的成本如何,队列将获得多大以及条目保持“无法上传”状态多长时间的情况下,无法确定效率是否可能是一个问题。

但是,更有效地完成此操作肯定是可能。例如,如果您可以安排从“不可上载”到“可上载”的转换触发某种事件,那么您可以安排事件处理程序将UploadItem添加到队列中。

对于UploadItem对象集合的循环扫描可能比每次从队列开始扫描更有效。其他可能的策略也可能更好。

但是这些替代方法也可能会改变上传的顺序......如果这对你来说是个问题。

  

使用迭代器检索项目是否有任何不利影响?

ConcurrentLinkedQueue的迭代器是weakly consistent。这意味着您无法保证看到迭代开始后添加的条目。对您的用例而言,这可能不是问题。 (如果下载偶尔会延迟到下一轮队列轮询,我觉得这很重要。)

  

这将在Android上运行,Android仍然使用Java 6.面对Lock-Free Concurrent Linked List in JavaConcurrentLinkedQueue$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)

使用PriorityQueueComparator首先在canUpload进行比较,然后按相反顺序进行比较。