1
1
/**
2
2
* Copyright 2013 Netflix, Inc.
3
- *
3
+ *
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
6
6
* You may obtain a copy of the License at
7
- *
7
+ *
8
8
* http://www.apache.org/licenses/LICENSE-2.0
9
- *
9
+ *
10
10
* Unless required by applicable law or agreed to in writing, software
11
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
17
18
18
import static org .mockito .Mockito .*;
19
19
20
- import java .util .LinkedList ;
21
- import java .util .Queue ;
20
+ import java .util .PriorityQueue ;
22
21
import java .util .concurrent .TimeUnit ;
23
22
24
23
import org .junit .Test ;
@@ -39,46 +38,62 @@ public static CurrentThreadScheduler getInstance() {
39
38
return INSTANCE ;
40
39
}
41
40
42
- private static final ThreadLocal <Queue < DiscardableAction <?>>> QUEUE = new ThreadLocal <Queue < DiscardableAction <?> >>();
41
+ private static final ThreadLocal <PriorityQueue < TimedAction >> QUEUE = new ThreadLocal <PriorityQueue < TimedAction >>();
43
42
44
43
private CurrentThreadScheduler () {
45
44
}
46
45
47
46
@ Override
48
47
public <T > Subscription schedule (T state , Func2 <Scheduler , T , Subscription > action ) {
49
48
DiscardableAction <T > discardableAction = new DiscardableAction <T >(state , action );
50
- enqueue (discardableAction );
49
+ enqueue (discardableAction , now () );
51
50
return discardableAction ;
52
51
}
53
52
54
53
@ Override
55
54
public <T > Subscription schedule (T state , Func2 <Scheduler , T , Subscription > action , long dueTime , TimeUnit unit ) {
56
- // since we are executing immediately on this thread we must cause this thread to sleep
57
- // TODO right now the 'enqueue' does not take delay into account so if another task is enqueued after this it will
58
- // wait behind the sleeping action ... should that be the case or should it be allowed to proceed ahead of the delayed action?
59
- return schedule (state , new SleepingAction <T >(action , this , dueTime , unit ));
55
+ long execTime = now () + unit .toMillis (dueTime );
56
+
57
+ DiscardableAction <T > discardableAction = new DiscardableAction <T >(state , new SleepingAction <T >(action , this , execTime ));
58
+ enqueue (discardableAction , execTime );
59
+ return discardableAction ;
60
60
}
61
61
62
- private void enqueue (DiscardableAction <?> action ) {
63
- Queue < DiscardableAction <?> > queue = QUEUE .get ();
62
+ private void enqueue (DiscardableAction <?> action , long execTime ) {
63
+ PriorityQueue < TimedAction > queue = QUEUE .get ();
64
64
boolean exec = queue == null ;
65
65
66
66
if (exec ) {
67
- queue = new LinkedList < DiscardableAction <?> >();
67
+ queue = new PriorityQueue < TimedAction >();
68
68
QUEUE .set (queue );
69
69
}
70
70
71
- queue .add (action );
71
+ queue .add (new TimedAction ( action , execTime ) );
72
72
73
73
if (exec ) {
74
74
while (!queue .isEmpty ()) {
75
- queue .poll ().call (this );
75
+ queue .poll ().action . call (this );
76
76
}
77
77
78
78
QUEUE .set (null );
79
79
}
80
80
}
81
81
82
+ private static class TimedAction implements Comparable <TimedAction > {
83
+ final DiscardableAction <?> action ;
84
+ final Long execTime ;
85
+
86
+ private TimedAction (DiscardableAction <?> action , Long execTime ) {
87
+ this .action = action ;
88
+ this .execTime = execTime ;
89
+ }
90
+
91
+ @ Override
92
+ public int compareTo (TimedAction timedAction ) {
93
+ return execTime .compareTo (timedAction .execTime );
94
+ }
95
+ }
96
+
82
97
public static class UnitTest {
83
98
84
99
@ Test
@@ -146,6 +161,29 @@ public void testSequenceOfActions() {
146
161
147
162
}
148
163
164
+ @ Test
165
+ public void testSequenceOfDelayedActions () {
166
+ final CurrentThreadScheduler scheduler = new CurrentThreadScheduler ();
167
+
168
+ final Action0 first = mock (Action0 .class );
169
+ final Action0 second = mock (Action0 .class );
170
+
171
+ scheduler .schedule (new Action0 () {
172
+ @ Override
173
+ public void call () {
174
+ scheduler .schedule (first , 30 , TimeUnit .MILLISECONDS );
175
+ scheduler .schedule (second , 10 , TimeUnit .MILLISECONDS );
176
+ }
177
+ });
178
+
179
+ InOrder inOrder = inOrder (first , second );
180
+
181
+ inOrder .verify (second , times (1 )).call ();
182
+ inOrder .verify (first , times (1 )).call ();
183
+
184
+
185
+ }
186
+
149
187
}
150
188
151
189
}
0 commit comments