Skip to content

Commit 8ce332e

Browse files
hansonrhansonr
authored andcommitted
Implements Executors.schedule with delay
1 parent b2d6f44 commit 8ce332e

File tree

9 files changed

+111
-57
lines changed

9 files changed

+111
-57
lines changed
295 Bytes
Binary file not shown.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20201203124442
1+
20201203153534
295 Bytes
Binary file not shown.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20201203124442
1+
20201203153534
295 Bytes
Binary file not shown.

sources/net.sf.j2s.java.core/src/java/util/concurrent/ScheduledThreadPoolExecutor.java

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535

3636
package java.util.concurrent;
3737
import java.util.concurrent.atomic.*;
38+
39+
import swingjs.JSToolkit;
40+
3841
import java.util.*;
3942

4043
/**
@@ -156,62 +159,63 @@ public class ScheduledThreadPoolExecutor
156159
private static final AtomicLong sequencer = new AtomicLong(0);
157160

158161
/**
159-
* Returns current nanosecond time.
162+
* Returns current millisecond time.
160163
*/
161-
final long now() {
162-
return System.nanoTime();
164+
final long nowms() {
165+
return System.currentTimeMillis();
166+
// return System.nanoTime();
163167
}
164168

165169
private class ScheduledFutureTask<V>
166170
extends FutureTask<V> implements RunnableScheduledFuture<V> {
167171

168172
/** Sequence number to break ties FIFO */
169173
private final long sequenceNumber;
170-
/** The time the task is enabled to execute in nanoTime units */
171-
private long time;
174+
/** The time the task is enabled to execute in MilliTime units */
175+
private long timems;
172176
/**
173-
* Period in nanoseconds for repeating tasks. A positive
177+
* Period in milliseconds for repeating tasks. A positive
174178
* value indicates fixed-rate execution. A negative value
175179
* indicates fixed-delay execution. A value of 0 indicates a
176180
* non-repeating task.
177181
*/
178-
private final long period;
182+
private final long periodms;
179183

180184
/** The actual task to be re-enqueued by reExecutePeriodic */
181185
RunnableScheduledFuture<V> outerTask = this;
182186

183187
/**
184-
* Creates a one-shot action with given nanoTime-based trigger time.
188+
* Creates a one-shot action with given milliTime-based trigger time.
185189
*/
186-
ScheduledFutureTask(Runnable r, V result, long ns) {
190+
ScheduledFutureTask(Runnable r, V result, long ms) {
187191
super(r, result);
188-
this.time = ns;
189-
this.period = 0;
192+
this.timems = ms;
193+
this.periodms = 0;
190194
this.sequenceNumber = sequencer.getAndIncrement();
191195
}
192196

193197
/**
194-
* Creates a periodic action with given nano time and period.
198+
* Creates a periodic action with given milli time and period.
195199
*/
196-
ScheduledFutureTask(Runnable r, V result, long ns, long period) {
200+
ScheduledFutureTask(Runnable r, V result, long ms, long period) {
197201
super(r, result);
198-
this.time = ns;
199-
this.period = period;
202+
this.timems = ms;
203+
this.periodms = period;
200204
this.sequenceNumber = sequencer.getAndIncrement();
201205
}
202206

203207
/**
204-
* Creates a one-shot action with given nanoTime-based trigger.
208+
* Creates a one-shot action with given milliTime-based trigger.
205209
*/
206210
ScheduledFutureTask(Callable<V> callable, long ns) {
207211
super(callable);
208-
this.time = ns;
209-
this.period = 0;
212+
this.timems = ns;
213+
this.periodms = 0;
210214
this.sequenceNumber = sequencer.getAndIncrement();
211215
}
212216

213217
public long getDelay(TimeUnit unit) {
214-
long d = unit.convert(time - now(), TimeUnit.NANOSECONDS);
218+
long d = unit.convert(timems - nowms(), TimeUnit.MILLISECONDS);
215219
return d;
216220
}
217221

@@ -220,7 +224,7 @@ public int compareTo(Delayed other) {
220224
return 0;
221225
if (other instanceof ScheduledFutureTask) {
222226
ScheduledFutureTask<?> x = (ScheduledFutureTask<?>)other;
223-
long diff = time - x.time;
227+
long diff = timems - x.timems;
224228
if (diff < 0)
225229
return -1;
226230
else if (diff > 0)
@@ -230,8 +234,8 @@ else if (sequenceNumber < x.sequenceNumber)
230234
else
231235
return 1;
232236
}
233-
long d = (getDelay(TimeUnit.NANOSECONDS) -
234-
other.getDelay(TimeUnit.NANOSECONDS));
237+
long d = (getDelay(TimeUnit.MILLISECONDS) -
238+
other.getDelay(TimeUnit.MILLISECONDS));
235239
return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
236240
}
237241

@@ -241,18 +245,18 @@ else if (sequenceNumber < x.sequenceNumber)
241245
* @return true if periodic
242246
*/
243247
public boolean isPeriodic() {
244-
return period != 0;
248+
return periodms != 0;
245249
}
246250

247251
/**
248252
* Sets the next time to run for a periodic task.
249253
*/
250254
private void setNextRunTime() {
251-
long p = period;
255+
long p = periodms;
252256
if (p > 0)
253-
time += p;
257+
timems += p;
254258
else
255-
time = now() - p;
259+
timems = nowms() - p;
256260
}
257261

258262
/**
@@ -283,6 +287,7 @@ boolean canRunInCurrentRunState(boolean periodic) {
283287
executeExistingDelayedTasksAfterShutdown);
284288
}
285289

290+
Map<Integer, RunnableScheduledFuture<?>> todo = new HashMap<>();
286291
/**
287292
* Main execution method for delayed or periodic tasks. If pool is shut down,
288293
* rejects the task. Otherwise adds task to queue and starts a thread, if
@@ -304,7 +309,13 @@ private void delayedExecute(RunnableScheduledFuture<?> task) {
304309

305310
if (/** @j2sNative true || */
306311
false) {
307-
new Thread(task).start();
312+
int[] id = new int[1];
313+
todo.put(id[0] = JSToolkit.dispatch(new Thread(() -> {
314+
RunnableScheduledFuture<?> me = todo.remove(id[0]);
315+
if (me != null)
316+
task.run();
317+
}), Math.max(-1, (int) task.getDelay(TimeUnit.MILLISECONDS)), 0), task);
318+
308319
} else /** @j2sIgnore */
309320
{
310321
super.getQueue().add(task);
@@ -402,7 +413,7 @@ protected <V> RunnableScheduledFuture<V> decorateTask(
402413
* @throws IllegalArgumentException if {@code corePoolSize < 0}
403414
*/
404415
public ScheduledThreadPoolExecutor(int corePoolSize) {
405-
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
416+
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.MILLISECONDS,
406417
new DelayedWorkQueue());
407418
}
408419

@@ -419,7 +430,7 @@ public ScheduledThreadPoolExecutor(int corePoolSize) {
419430
*/
420431
public ScheduledThreadPoolExecutor(int corePoolSize,
421432
ThreadFactory threadFactory) {
422-
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
433+
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.MILLISECONDS,
423434
new DelayedWorkQueue(), threadFactory);
424435
}
425436

@@ -436,7 +447,7 @@ public ScheduledThreadPoolExecutor(int corePoolSize,
436447
*/
437448
public ScheduledThreadPoolExecutor(int corePoolSize,
438449
RejectedExecutionHandler handler) {
439-
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
450+
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.MILLISECONDS,
440451
new DelayedWorkQueue(), handler);
441452
}
442453

@@ -457,7 +468,7 @@ public ScheduledThreadPoolExecutor(int corePoolSize,
457468
public ScheduledThreadPoolExecutor(int corePoolSize,
458469
ThreadFactory threadFactory,
459470
RejectedExecutionHandler handler) {
460-
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,
471+
super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.MILLISECONDS,
461472
new DelayedWorkQueue(), threadFactory, handler);
462473
}
463474

@@ -467,7 +478,7 @@ public ScheduledFuture<?> schedule(Runnable command,
467478
if (command == null || unit == null)
468479
throw new NullPointerException();
469480
if (delay < 0) delay = 0;
470-
long triggerTime = now() + unit.toNanos(delay);
481+
long triggerTime = nowms() + unit.toMillis(delay);
471482
RunnableScheduledFuture<?> t = decorateTask(command,
472483
new ScheduledFutureTask<Void>(command, null, triggerTime));
473484
delayedExecute(t);
@@ -480,7 +491,7 @@ public <V> ScheduledFuture<V> schedule(Callable<V> callable,
480491
if (callable == null || unit == null)
481492
throw new NullPointerException();
482493
if (delay < 0) delay = 0;
483-
long triggerTime = now() + unit.toNanos(delay);
494+
long triggerTime = nowms() + unit.toMillis(delay);
484495
RunnableScheduledFuture<V> t = decorateTask(callable,
485496
new ScheduledFutureTask<V>(callable, triggerTime));
486497
delayedExecute(t);
@@ -496,12 +507,12 @@ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
496507
if (period <= 0)
497508
throw new IllegalArgumentException();
498509
if (initialDelay < 0) initialDelay = 0;
499-
long triggerTime = now() + unit.toNanos(initialDelay);
510+
long triggerTime = nowms() + unit.toMillis(initialDelay);
500511
ScheduledFutureTask<Void> sft =
501512
new ScheduledFutureTask<Void>(command,
502513
null,
503514
triggerTime,
504-
unit.toNanos(period));
515+
unit.toMillis(period));
505516
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
506517
sft.outerTask = t;
507518
delayedExecute(t);
@@ -517,12 +528,12 @@ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
517528
if (delay <= 0)
518529
throw new IllegalArgumentException();
519530
if (initialDelay < 0) initialDelay = 0;
520-
long triggerTime = now() + unit.toNanos(initialDelay);
531+
long triggerTime = nowms() + unit.toMillis(initialDelay);
521532
ScheduledFutureTask<Void> sft =
522533
new ScheduledFutureTask<Void>(command,
523534
null,
524535
triggerTime,
525-
unit.toNanos(-delay));
536+
unit.toMillis(-delay));
526537
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
527538
sft.outerTask = t;
528539
delayedExecute(t);
@@ -550,22 +561,22 @@ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
550561
* @throws NullPointerException {@inheritDoc}
551562
*/
552563
public void execute(Runnable command) {
553-
schedule(command, 0, TimeUnit.NANOSECONDS);
564+
schedule(command, 0, TimeUnit.MILLISECONDS);
554565
}
555566

556567
// Override AbstractExecutorService methods
557568

558569
public Future<?> submit(Runnable task) {
559-
return schedule(task, 0, TimeUnit.NANOSECONDS);
570+
return schedule(task, 0, TimeUnit.MILLISECONDS);
560571
}
561572

562573
public <T> Future<T> submit(Runnable task, T result) {
563574
return schedule(Executors.callable(task, result),
564-
0, TimeUnit.NANOSECONDS);
575+
0, TimeUnit.MILLISECONDS);
565576
}
566577

567578
public <T> Future<T> submit(Callable<T> task) {
568-
return schedule(task, 0, TimeUnit.NANOSECONDS);
579+
return schedule(task, 0, TimeUnit.MILLISECONDS);
569580
}
570581

571582
/**

sources/net.sf.j2s.java.core/src/test/Test_Future.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@
1818

1919
import test.baeldung.doublecolon.Computer;
2020
import test.baeldung.doublecolon.MacbookPro;
21+
22+
import java.awt.Color;
2123
import java.awt.event.ActionEvent;
2224
import java.util.concurrent.CompletableFuture;
2325
import java.util.concurrent.CompletionStage;
2426
import java.util.concurrent.Executor;
2527
import java.util.concurrent.ExecutorService;
2628
import java.util.concurrent.Executors;
2729
import java.util.concurrent.Future;
30+
import java.util.concurrent.ScheduledExecutorService;
31+
import java.util.concurrent.TimeUnit;
2832
import java.util.function.Supplier;
2933

3034
import javax.swing.JButton;
@@ -36,39 +40,48 @@ public class Test_Future extends JFrame {
3640
Executor executor = (Runnable r) -> {
3741
new Thread(r).start();
3842
};
43+
private JButton button;
3944

4045
public Test_Future() {
4146
setVisible(true);
4247
setBounds(500, 300, 400, 300);
4348
setDefaultCloseOperation(EXIT_ON_CLOSE);
44-
JButton button = new JButton("PRESS ME");
49+
button = new JButton("PRESS ME");
4550
button.addActionListener((ActionEvent e) -> {
4651
btnAction();
4752
});
4853
add(button);
4954
}
5055

56+
Color lastColor = null;
57+
5158
private void btnAction() {
5259
System.out.println("button pressed");
60+
61+
Executors.newSingleThreadScheduledExecutor().schedule(() -> {
62+
button.setForeground(lastColor = (lastColor == Color.red ? Color.blue : Color.red));
63+
System.out.println("task complete");
64+
}, 3000, TimeUnit.MILLISECONDS);
65+
5366
CompletionStage<String> future = longJob();
5467
future.thenAccept((value) -> {
5568
System.out.format("returned with %s%n", value);
5669
});
57-
ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
58-
Future<?> f = dialogExecutor.submit(() -> {
70+
71+
ExecutorService dialogExecutor = Executors.newSingleThreadExecutor();
72+
Future<?> f = dialogExecutor.submit(() -> {
5973
System.out.println("dialog runnable 1");
6074
});
61-
dialogExecutor.submit(() -> {
75+
dialogExecutor.submit(() -> {
6276
System.out.println("dialog runnable 2");
6377
});
64-
dialogExecutor.submit(() -> {
78+
dialogExecutor.submit(() -> {
6579
System.out.println("dialog runnable 3");
6680
System.out.println(f.toString() + f.isDone());
6781
});
6882
System.out.println("CompletionStage started");
6983
System.out.println(f.toString() + f.isDone());
70-
71-
84+
7285
}
7386

7487
CompletableFuture<String> longJob() {

0 commit comments

Comments
 (0)