Changing delay, and hence the order, in a DelayQueue
So first of all you need to to create an instance of Delayed, this is a very simple implementation that with the switch of a flag you can basically invert the timeout order in the list. (And add a suitable offset so things happen in the right order
01 02 03 04 05 06 07 08 09 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 | static int COUNT= 100 ; class DelayedSwap implements Delayed, Comparable<Delayed> { int index = 0 ; volatile boolean swap = false ; long starttime; public DelayedSwap( int index, long starttime) { super (); this .index = index; this .starttime = starttime; } private long getDelay() { return (swap ? starttime + ( 2 *COUNT - index) * 100 : starttime + index * 100 ) - System.currentTimeMillis(); } public String toString() { return index + ' swapped ' + swap + ' delay ' + getDelay(); } @Override public long getDelay(TimeUnit unit) { return unit.convert(getDelay(), TimeUnit.MILLISECONDS); } @Override public int compareTo(Delayed delayed) { if (delayed == this ) return 0 ; return ( int )(getDelay(TimeUnit.MILLISECONDS) - delayed.getDelay(TimeUnit.MILLISECONDS)); } } |
So to test this I created a method that would create a bunch of the DelayedSwap objects and half way through processing the list switch the flag so altering the order of expiration.
01 02 03 04 05 06 07 08 09 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 | public static void main(String[] args) throws InterruptedException { long start = System.currentTimeMillis(); final List delayed = new ArrayList (); for ( int i = 1 ; i < COUNT; i++) { delayed.add( new DelayedSwap(i, start)); } final DelayQueue dq = new DelayQueue(); dq.addAll(delayed); new Thread( new Runnable() { @Override public void run() { try { TimeUnit.SECONDS.sleep( 5 ); } catch (InterruptedException e) { } for (DelayedSwap d : delayed) { d.swap = true ; } } }).start(); while (!dq.isEmpty()) { System.out.println(dq.take()); } } |
So what I was expecting was the elements 1-50 ish written out in the correct order but instead after the swap over the elements are coming out in an arbitrary order quite far away from the request delay time.
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 | 1 swapped false delay - 19 2 swapped false delay - 4 3 swapped false delay - 4 4 swapped false delay - 4 5 swapped false delay - 4 6 swapped false delay - 4 7 swapped false delay - 4 8 swapped false delay - 4 9 swapped false delay - 4 10 swapped false delay - 4 11 swapped false delay - 4 12 swapped false delay - 4 13 swapped false delay - 4 14 swapped false delay - 4 15 swapped false delay - 4 16 swapped false delay - 4 17 swapped false delay - 4 18 swapped false delay - 4 19 swapped false delay - 4 20 swapped false delay - 4 21 swapped false delay - 4 22 swapped false delay - 4 23 swapped false delay - 4 24 swapped false delay - 4 25 swapped false delay - 4 26 swapped false delay - 4 27 swapped false delay - 4 28 swapped false delay - 4 29 swapped false delay - 4 30 swapped false delay - 4 31 swapped false delay - 4 32 swapped false delay - 4 33 swapped false delay - 4 34 swapped false delay - 4 35 swapped false delay - 4 36 swapped false delay - 4 37 swapped false delay - 4 38 swapped false delay - 4 39 swapped false delay - 5 40 swapped false delay - 4 41 swapped false delay - 4 42 swapped false delay - 5 43 swapped false delay - 4 44 swapped false delay - 5 45 swapped false delay - 5 46 swapped false delay - 5 47 swapped false delay - 5 48 swapped false delay - 5 49 swapped false delay - 5 50 swapped false delay - 5 51 swapped true delay - 6 94 swapped true delay - 4306 96 swapped true delay - 4506 87 swapped true delay - 3606 91 swapped true delay - 4006 97 swapped true delay - 4606 95 swapped true delay - 4406 98 swapped true delay - 4706 92 swapped true delay - 4106 82 swapped true delay - 3106 80 swapped true delay - 2906 90 swapped true delay - 3906 93 swapped true delay - 4206 74 swapped true delay - 2306 99 swapped true delay - 4806 70 swapped true delay - 1906 69 swapped true delay - 1806 66 swapped true delay - 1506 83 swapped true delay - 3206 62 swapped true delay - 1107 61 swapped true delay - 1007 58 swapped true delay - 707 71 swapped true delay - 2007 89 swapped true delay - 3807 85 swapped true delay - 3407 78 swapped true delay - 2707 86 swapped true delay - 3507 81 swapped true delay - 3007 88 swapped true delay - 3707 84 swapped true delay - 3307 79 swapped true delay - 2807 76 swapped true delay - 2507 72 swapped true delay - 2107 68 swapped true delay - 1707 65 swapped true delay - 1407 60 swapped true delay - 907 57 swapped true delay - 608 55 swapped true delay - 408 75 swapped true delay - 2408 77 swapped true delay - 2608 73 swapped true delay - 2208 63 swapped true delay - 1208 67 swapped true delay - 1608 64 swapped true delay - 1308 59 swapped true delay - 808 56 swapped true delay - 508 54 swapped true delay - 308 53 swapped true delay - 208 52 swapped true delay - 108 Process exited with exit code 0 . |
So the trick is when you know you are going to modify the delay is to remove and then re-add the element to the queue.
1 2 3 4 5 6 7 8 | // Replacement swap loop for (DelayedSwap d : delayed) { if (dq.remove(d)) { d.swap = true ; dq.add(d); } } |
This run produces a more sensible set of results:
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 | 1 swapped false delay - 4 2 swapped false delay - 8 3 swapped false delay - 14 4 swapped false delay - 8 5 swapped false delay - 4 6 swapped false delay - 4 7 swapped false delay - 4 8 swapped false delay - 4 9 swapped false delay - 4 10 swapped false delay - 4 11 swapped false delay - 4 12 swapped false delay - 4 13 swapped false delay - 4 14 swapped false delay - 4 15 swapped false delay - 4 16 swapped false delay - 4 17 swapped false delay - 4 18 swapped false delay - 8 19 swapped false delay - 4 20 swapped false delay - 4 21 swapped false delay - 4 22 swapped false delay - 4 23 swapped false delay - 4 24 swapped false delay - 4 25 swapped false delay - 4 26 swapped false delay - 4 27 swapped false delay - 4 28 swapped false delay - 4 29 swapped false delay - 4 30 swapped false delay - 4 31 swapped false delay - 4 32 swapped false delay - 4 33 swapped false delay - 4 34 swapped false delay - 4 35 swapped false delay - 4 36 swapped false delay - 4 37 swapped false delay - 4 38 swapped false delay - 4 39 swapped false delay - 5 40 swapped false delay - 5 41 swapped false delay - 5 42 swapped false delay - 4 43 swapped false delay - 4 44 swapped false delay - 5 45 swapped false delay - 5 46 swapped false delay - 5 47 swapped false delay - 5 48 swapped false delay - 5 49 swapped false delay - 5 50 swapped false delay - 5 99 swapped true delay - 5 98 swapped true delay - 5 97 swapped true delay - 11 96 swapped true delay - 1 95 swapped true delay - 5 94 swapped true delay - 9 93 swapped true delay - 5 92 swapped true delay - 5 91 swapped true delay - 5 90 swapped true delay - 5 89 swapped true delay - 5 88 swapped true delay - 5 87 swapped true delay - 5 86 swapped true delay - 5 85 swapped true delay - 5 84 swapped true delay - 5 83 swapped true delay - 5 82 swapped true delay - 5 81 swapped true delay - 5 80 swapped true delay - 5 79 swapped true delay - 5 78 swapped true delay - 5 77 swapped true delay - 5 76 swapped true delay - 5 75 swapped true delay - 5 74 swapped true delay - 5 73 swapped true delay - 5 72 swapped true delay - 6 71 swapped true delay - 5 70 swapped true delay - 5 69 swapped true delay - 5 68 swapped true delay - 5 67 swapped true delay - 5 66 swapped true delay - 5 65 swapped true delay - 5 64 swapped true delay - 5 63 swapped true delay - 6 62 swapped true delay - 5 61 swapped true delay - 6 60 swapped true delay - 6 59 swapped true delay - 6 58 swapped true delay - 6 57 swapped true delay - 6 56 swapped true delay - 6 55 swapped true delay - 6 54 swapped true delay - 6 53 swapped true delay - 6 52 swapped true delay - 6 51 swapped true delay - 6 Process exited with exit code 0 . |
I don’t think this is a bug in the object itself, as you wouldn’t expect a HashTable to orders it’s self when the key changes, but I was a little bit surprise by the behaviour.
Happy coding and don’t forget to share!
Reference: Changing delay, and hence the order, in a DelayQueue from our JCG partner Gerard Davison at the Gerard Davison’s blog blog.