Oh hai. 
Ik ben bezig met het schrijven van een downloadmanager aangezien die pas vanaf Android 2.3 standaard in het framework zit. Gegeven de volgende code:
Vervolgens mijn testcase:
Url's zijn (uiteraard) ingekort, dat is in de app zelf gewoon een echte url.
Wat nu de bedoeling is, en wat ik dacht ook voor elkaar te krijgen met die PriorityQueue en mijn compareTo-method, is dat eerst de eerste 3 aanroepen in de queue gezet worden (queueDownload) en vervolgens meteen als thread gestart worden (checkDownloads). Daarna wordt de vierde aanroep gedaan, die een PRIORITY_HIGH heeft. Er zijn dan geen slots meer vrij, dus die wordt gequeued. Aanroep 5 heeft een urgent-prioriteit, en die wordt dan ook meteen geactiveerd. Aanroepen 6 t/m 9 gaan op de queue, en aanroep 10 is weer urgent en wordt dus ook meteen gestart. Ik ga uit van 3 normale downloadslots by default, plus maximaal 3 extra slots voor urgent downloads; bij de uitvoer van deze code verwacht ik dus dat 5 van de 6 slots bezet zijn. Middels een semaphore zorg ik ervoor dat er pas weer iets van de queue getrokken wordt als er minder dan 3 slots in gebruik zijn. Middels een sequence-number zorg ik ervoor dat spul met dezelfde priority gewoon FiFo binnengehaald wordt.
De voorwaarde (downloadSemaphore.availablePermits() > maxConcurrentDownloads) op regel 38 zorgt ervoor dat mijn semaphore met een size van 6 hooguit 3 keer acquired wordt door "normale" downloads zodat ik de overige drie slots aan urgent downloads kan toekennen.
Wat ik nu verwacht is deze volgorde van (het beginnen met) binnenhalen van files:
Ik ben bezig met het schrijven van een downloadmanager aangezien die pas vanaf Android 2.3 standaard in het framework zit. Gegeven de volgende code:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| public class DownloadManager { public static final int PRIORITY_URGENT = 100; public static final int PRIORITY_HIGH = 75; public static final int PRIORITY_NORMAL = 50; public static final int PRIORITY_LOW = 25; public static final int PRIORITY_IDLE = 0; private PriorityQueue<DownloadTask> downloadQueue = new PriorityQueue<DownloadTask>(); private int downloadSequence = 0; public class DownloadTask extends AsyncTask<Void, Void, DownloadTask> implements Comparable<DownloadTask> { @Override public int compareTo(DownloadTask other) { if (other == null) return 1; if (this.priority == other.priority) return this.sequence - other.sequence; return other.priority - this.priority; } } public synchronized DownloadTask queueDownload(URL url, int priority, OnDownloadCompletedListener onCompleted, boolean undub) { DownloadTask dt = new DownloadTask(this, url, priority, onCompleted, downloadSequence++); // *Knip undub-code* downloadQueue.add(dt); checkDownloads(); return dt; } protected synchronized void checkDownloads() { while (downloadQueue.peek() != null && (downloadQueue.peek().priority == PRIORITY_URGENT || (downloadSemaphore.availablePermits() > maxConcurrentDownloads))) { downloadQueue.remove().execute(); } } } |
Vervolgens mijn testcase:
Java:
1
2
3
4
5
6
7
8
9
10
| dMgr.queueDownload(new URL("151"), DownloadManager.PRIORITY_IDLE, listener); dMgr.queueDownload(new URL("152"), DownloadManager.PRIORITY_LOW, listener); dMgr.queueDownload(new URL("153"), DownloadManager.PRIORITY_NORMAL, listener); dMgr.queueDownload(new URL("154"), DownloadManager.PRIORITY_HIGH, listener); dMgr.queueDownload(new URL("155"), DownloadManager.PRIORITY_URGENT, listener); dMgr.queueDownload(new URL("156"), DownloadManager.PRIORITY_IDLE, listener); dMgr.queueDownload(new URL("157"), DownloadManager.PRIORITY_LOW, listener); dMgr.queueDownload(new URL("158"), DownloadManager.PRIORITY_NORMAL, listener); dMgr.queueDownload(new URL("159"), DownloadManager.PRIORITY_HIGH, listener); dMgr.queueDownload(new URL("160"), DownloadManager.PRIORITY_URGENT, listener); |
Url's zijn (uiteraard) ingekort, dat is in de app zelf gewoon een echte url.
Wat nu de bedoeling is, en wat ik dacht ook voor elkaar te krijgen met die PriorityQueue en mijn compareTo-method, is dat eerst de eerste 3 aanroepen in de queue gezet worden (queueDownload) en vervolgens meteen als thread gestart worden (checkDownloads). Daarna wordt de vierde aanroep gedaan, die een PRIORITY_HIGH heeft. Er zijn dan geen slots meer vrij, dus die wordt gequeued. Aanroep 5 heeft een urgent-prioriteit, en die wordt dan ook meteen geactiveerd. Aanroepen 6 t/m 9 gaan op de queue, en aanroep 10 is weer urgent en wordt dus ook meteen gestart. Ik ga uit van 3 normale downloadslots by default, plus maximaal 3 extra slots voor urgent downloads; bij de uitvoer van deze code verwacht ik dus dat 5 van de 6 slots bezet zijn. Middels een semaphore zorg ik ervoor dat er pas weer iets van de queue getrokken wordt als er minder dan 3 slots in gebruik zijn. Middels een sequence-number zorg ik ervoor dat spul met dezelfde priority gewoon FiFo binnengehaald wordt.
De voorwaarde (downloadSemaphore.availablePermits() > maxConcurrentDownloads) op regel 38 zorgt ervoor dat mijn semaphore met een size van 6 hooguit 3 keer acquired wordt door "normale" downloads zodat ik de overige drie slots aan urgent downloads kan toekennen.
Wat ik nu verwacht is deze volgorde van (het beginnen met) binnenhalen van files:
- 151 (idle, gequeued toen alledrie de slots leeg waren, dus meteen gestart)
- 152 (low, gequeued met 2 slots vrij, dus meteen gestart)
- 153 (normal, gequeued in het laatste slot, dus meteen gestart)
- 155 (urgent, dus gequeued in een anderzijds onbeschikbaar slot)
- 160 (urgent, idem)
- 154 (high, dus hoogste prio die gequeued kan worden)
- 159 (high, maar later toegevoegd dan 154)
- 158 (normal)
- 157 (low)
- 156 (idle)
[ Voor 16% gewijzigd door NMe op 16-04-2011 02:28 ]
'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.