我有一個沒有保存按鈕的應用程序;後臺自動保存。當用戶使用應用程序時,創建任務並放入隊列中執行。其中一些延遲,例如,當你開始輸入時,我會等待200毫秒,然後再更新數據庫中的相應值。需要混合使用Delayed和Map
爲了使這個更簡單的使用代碼明智的,我想能夠添加一個任務延遲和一個「關鍵」的隊列。如果已經有一個具有相同「密鑰」的任務,那麼我的第二個任務應該被忽略(因爲同一個操作已經排隊)。
這樣的事情已經存在嗎?
我有一個沒有保存按鈕的應用程序;後臺自動保存。當用戶使用應用程序時,創建任務並放入隊列中執行。其中一些延遲,例如,當你開始輸入時,我會等待200毫秒,然後再更新數據庫中的相應值。需要混合使用Delayed和Map
爲了使這個更簡單的使用代碼明智的,我想能夠添加一個任務延遲和一個「關鍵」的隊列。如果已經有一個具有相同「密鑰」的任務,那麼我的第二個任務應該被忽略(因爲同一個操作已經排隊)。
這樣的事情已經存在嗎?
我想你應該看看TreeMap類。使用可以傳遞比較器的構造函數。這樣你可以讓Map排序爲Delayed(因爲這個類實現了Comparable接口)。在向地圖添加「任務」之前,請使用containsKey方法檢查密鑰是否已存在。
我認爲這是最好的解決方案。一個隊列不允許我擺脫重複的任務,所以我需要一個地圖,或者可能是一個TreeMap和一個Set(所以我可以通過延遲*和*查找重複鍵)。 – 2010-08-23 07:46:30
+1有點不明顯,優雅的解決方案。 – user359996 2010-10-10 20:58:54
這是我的理解問題,並會接受挑戰:
任務包裝紙包裹任務或命令,並增加了額外的價值,爲任務和標識的延遲。我明白,兩項任務可能具有相同的「關鍵」,所以我們不能只執行任務哈希值。
public TaskWrapper<T> {
private T task;
private long delayInMillis;
private long key;
public TaskWrapper(T task, long delayInMillis, long key) {
this.task = task;
this.delayInMillis = delayInMillis;
this.key = key;
}
// getter, setters, and so on
public boolean equals(Object o) {
if (o == null || !(o instanceof TaskWrapper)) return false;
return key == ((TaskWrapper) o).key;
}
}
一個隊列裝飾器添加了類似'set'的行爲。一個隊列沒有'contains'方法,所以我拿一個額外的Set來記錄實際被請求的對象。所有更改隊列的方法都將實現,以保持內部隊列和集合之間的一致性。此快速草稿不是線程安全的,只顯示add
方法。
public SetQueue<TaskWrapper> implements Queue<T> {
private Queue<TaskWrapper> queue;
private Set<TaskWrapper> set = new HashSet<TaskWrapper>();
public SetQueue(Queue<TaskWrapper> queue) {
this.queue = queue;
}
// just to demonstrate the idea
public boolean add(TaskWrapper<?> task) {
if (set.contains(task)
return false;
boolean result = queue.add(task);
if (result)
set.add(task);
return result;
}
(可能充滿錯誤的,我沒有在手的IDE這只是一個草案)
一說我腦子裏浮現優雅的解決方案:使用一個線程池執行者有一個priority blocking queue作爲工作隊列。
當我將相同的任務添加到隊列時會發生什麼?如果我正確理解隊列,那麼可以有許多比較等於的任務。 – 2010-08-23 07:42:23
沒有關於具有相同優先級的元素排序的保證。如果您需要強制執行排序,則可以定義使用輔助鍵的自定義類或比較器來打破主要優先級值中的關係。 – 2010-08-30 19:32:56
DelayQueue可能更適合嗎? – user359996 2010-10-10 21:38:54
只是澄清 - 你使用標準隊列實現還是一些自定義數據結構?我們是否可以用所需的「集合」式行爲來裝飾? – 2010-08-16 08:11:05
目前,我將更新添加到標準隊列並啓動計時器。當計時器用完時,我將整個隊列推送到數據庫並提交。現在我正在考慮是否有更好的/不同的方式。 – 2010-08-16 11:52:07
您是否等到自第一次按鍵或最後一次(最近)以來已過200 ms?另外,有趣的問題 - 用例是什麼? – user359996 2010-10-10 20:48:19