2014-12-07 64 views
0

我有用例,其中一個隊列持有UploadItem(s)。隊列必須是線程安全的。 UploadItem有一個方法canUpload()。 UploadItems被添加到尾部的隊列中,但peek()和poll()必須返回canUpload()爲true的第一個UploadItem。這可能是頭上的項目或更新的項目。實質上,我希望項目在被準備好上傳之前被忽略,並且我希望隊列返回已準備好的最舊項目。如果輪詢不一定返回第一個項目,那麼ConcurrentLinkedQueue是一個很好的選擇嗎?

爲了解決這個問題,我擴展了一個ConcurrentLinkedQueue,並且我重寫了peek()和poll()。我已經同步了重寫方法,並且正在使用迭代器來檢索第一個有效的項目。

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上進行更新/修補(在其主要版本中)?

回答

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是關於Oracle/OpenJDK Java編寫的,而不是Apache Harvest/Android潔淨室的重新實現。

有誰知道Java是否通常在Android上更新/修補(在其主要版本中)?

你不能一概而論。

首先,Java庫的Android實現是與標準Oracle/OpenJDK代碼庫不同的代碼庫。所以後者的更新/補丁不適用於前者。其次,即使更新/補丁是針對標準的Android發行版製作的,也不能保證1)手機制造商會接受它們,2)他們會打到電話公司的分銷渠道,或3)個人智能手機業主將適用它們。

+0

「這兩個標準並不相互排斥。」同意;-) canUpload()很便宜。它比較單個日期變量。隊列通常不超過100個項目,但如果沒有可用的網絡連接,隊列可能會增加。我可以看到爲什麼你提出了循環法,因爲當網絡在長時間和隊列很長時間後變得可用時,由於每次輪詢()的迭代,性能可能會顯着降低。謝謝你討論這個。 – 2014-12-07 15:36:34

+0

根據你所說的話,我認爲效率不會是一個主要問題。如果是,那麼我的第一個建議(當項目變成「可上傳的」時加入隊列)應該接近最優。 – 2014-12-07 22:18:16

0

使用PriorityQueueComparator,它首先比較canUpload,然後按照相反的順序進行比較。

+0

您可以更改優先級隊列中的元素,使其隊列中的順序發生更改,而不會導致隊列的未定義行爲?我無法想象這是真的(純粹從實現的角度來看)甚至是 – Voo 2014-12-07 08:40:57

+0

PriorityQueue不是線程安全的,但我可能能夠使用PriorityBlockingQueue。 – 2014-12-07 15:24:32

相關問題