Skip to content

Commit 094073b

Browse files
authored
Merge pull request #184 from BobHanson/master
Implements Executor delayed and fixed rate periodic tasks
2 parents c95bea4 + b7229d8 commit 094073b

File tree

8 files changed

+127
-77
lines changed

8 files changed

+127
-77
lines changed
-195 Bytes
Binary file not shown.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20201203153534
1+
20201203173354
-195 Bytes
Binary file not shown.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
20201203153534
1+
20201203173354
-195 Bytes
Binary file not shown.

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

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,14 @@ private class ScheduledFutureTask<V>
172172
/** Sequence number to break ties FIFO */
173173
private final long sequenceNumber;
174174
/** The time the task is enabled to execute in MilliTime units */
175-
private long timems;
175+
long timems;
176176
/**
177177
* Period in milliseconds for repeating tasks. A positive
178178
* value indicates fixed-rate execution. A negative value
179179
* indicates fixed-delay execution. A value of 0 indicates a
180180
* non-repeating task.
181181
*/
182-
private final long periodms;
182+
final long periodms;
183183

184184
/** The actual task to be re-enqueued by reExecutePeriodic */
185185
RunnableScheduledFuture<V> outerTask = this;
@@ -303,17 +303,15 @@ private void delayedExecute(RunnableScheduledFuture<?> task) {
303303
if (isShutdown())
304304
reject(task);
305305
else {
306-
if (task.isPeriodic()) {
307-
swingjs.JSUtil.notImplemented("Periodic tasks");
308-
}
309-
310306
if (/** @j2sNative true || */
311307
false) {
312308
int[] id = new int[1];
313309
todo.put(id[0] = JSToolkit.dispatch(new Thread(() -> {
314-
RunnableScheduledFuture<?> me = todo.remove(id[0]);
315-
if (me != null)
310+
RunnableScheduledFuture<?> t = todo.remove(id[0]);
311+
if (t != null) {
316312
task.run();
313+
}
314+
317315
}), Math.max(-1, (int) task.getDelay(TimeUnit.MILLISECONDS)), 0), task);
318316

319317
} else /** @j2sIgnore */
@@ -335,11 +333,12 @@ private void delayedExecute(RunnableScheduledFuture<?> task) {
335333
*/
336334
void reExecutePeriodic(RunnableScheduledFuture<?> task) {
337335
if (canRunInCurrentRunState(true)) {
338-
super.getQueue().add(task);
339-
if (!canRunInCurrentRunState(true) && remove(task))
340-
task.cancel(false);
341-
else
342-
prestartCoreThread();
336+
delayedExecute(task);
337+
// super.getQueue().add(task);
338+
// if (!canRunInCurrentRunState(true) && remove(task))
339+
// task.cancel(false);
340+
// else
341+
// prestartCoreThread();
343342
}
344343
}
345344

@@ -348,25 +347,23 @@ void reExecutePeriodic(RunnableScheduledFuture<?> task) {
348347
* due to shutdown policy. Invoked within super.shutdown.
349348
*/
350349
@Override void onShutdown() {
351-
BlockingQueue<Runnable> q = super.getQueue();
350+
// BlockingQueue<Runnable> q = super.getQueue();
352351
boolean keepDelayed =
353352
getExecuteExistingDelayedTasksAfterShutdownPolicy();
354353
boolean keepPeriodic =
355354
getContinueExistingPeriodicTasksAfterShutdownPolicy();
356-
if (!keepDelayed && !keepPeriodic)
357-
q.clear();
358-
else {
355+
if (!keepDelayed && !keepPeriodic) {
356+
todo.clear();
357+
// q.clear();
358+
} else {
359359
// Traverse snapshot to avoid iterator exceptions
360-
for (Object e : q.toArray()) {
361-
if (e instanceof RunnableScheduledFuture) {
362-
RunnableScheduledFuture<?> t =
363-
(RunnableScheduledFuture<?>)e;
360+
for (Map.Entry<Integer, RunnableScheduledFuture<?>> e: todo.entrySet()) {
361+
RunnableScheduledFuture<?> t = e.getValue();
364362
if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) ||
365363
t.isCancelled()) { // also remove if already cancelled
366-
if (q.remove(t))
364+
todo.remove(t);
367365
t.cancel(false);
368366
}
369-
}
370367
}
371368
}
372369
tryTerminate();

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

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,7 @@ private void decrementWorkerCount() {
541541
* bounded by CAPACITY.
542542
*/
543543
private volatile int maximumPoolSize;
544+
private boolean stopped;
544545

545546
/**
546547
* The default rejected execution handler
@@ -689,34 +690,35 @@ private void advanceRunState(int targetState) {
689690
* allow access from ScheduledThreadPoolExecutor.
690691
*/
691692
final void tryTerminate() {
692-
for (;;) {
693-
int c = ctl.get();
694-
if (isRunning(c) ||
695-
runStateAtLeast(c, TIDYING) ||
696-
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
697-
return;
698-
if (workerCountOf(c) != 0) { // Eligible to terminate
699-
interruptIdleWorkers(ONLY_ONE);
700-
return;
701-
}
702-
703-
final ReentrantLock mainLock = this.mainLock;
704-
mainLock.lock();
705-
try {
706-
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
707-
try {
708-
terminated();
709-
} finally {
710-
ctl.set(ctlOf(TERMINATED, 0));
711-
termination.signalAll();
712-
}
713-
return;
714-
}
715-
} finally {
716-
mainLock.unlock();
717-
}
718-
// else retry on failed CAS
719-
}
693+
terminated();
694+
// for (;;) {
695+
// int c = ctl.get();
696+
// if (isRunning(c) ||
697+
// runStateAtLeast(c, TIDYING) ||
698+
// (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
699+
// return;
700+
// if (workerCountOf(c) != 0) { // Eligible to terminate
701+
// interruptIdleWorkers(ONLY_ONE);
702+
// return;
703+
// }
704+
//
705+
// final ReentrantLock mainLock = this.mainLock;
706+
// mainLock.lock();
707+
// try {
708+
// if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
709+
// try {
710+
// terminated();
711+
// } finally {
712+
// ctl.set(ctlOf(TERMINATED, 0));
713+
// termination.signalAll();
714+
// }
715+
// return;
716+
// }
717+
// } finally {
718+
// mainLock.unlock();
719+
// }
720+
// // else retry on failed CAS
721+
// }
720722
}
721723

722724
/*
@@ -841,8 +843,9 @@ void onShutdown() {
841843
* @param shutdownOK true if should return true if SHUTDOWN
842844
*/
843845
final boolean isRunningOrShutdown(boolean shutdownOK) {
844-
int rs = runStateOf(ctl.get());
845-
return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
846+
return (shutdownOK || !stopped);
847+
// int rs = runStateOf(ctl.get());
848+
// return rs == RUNNING || (rs == SHUTDOWN && shutdownOK);
846849
}
847850

848851
/**
@@ -1394,16 +1397,17 @@ else if (!addWorker(command, false))
13941397
* @throws SecurityException {@inheritDoc}
13951398
*/
13961399
public void shutdown() {
1397-
final ReentrantLock mainLock = this.mainLock;
1398-
mainLock.lock();
1399-
try {
1400-
checkShutdownAccess();
1401-
advanceRunState(SHUTDOWN);
1400+
// final ReentrantLock mainLock = this.mainLock;
1401+
// mainLock.lock();
1402+
// try {
1403+
// checkShutdownAccess();
1404+
// advanceRunState(SHUTDOWN);
1405+
stopped = true;
14021406
interruptIdleWorkers();
14031407
onShutdown(); // hook for ScheduledThreadPoolExecutor
1404-
} finally {
1405-
mainLock.unlock();
1406-
}
1408+
// } finally {
1409+
// mainLock.unlock();
1410+
// }
14071411
tryTerminate();
14081412
}
14091413

@@ -1437,7 +1441,7 @@ public List<Runnable> shutdownNow() {
14371441
}
14381442

14391443
public boolean isShutdown() {
1440-
return ! isRunning(ctl.get());
1444+
return stopped;//! isRunning(ctl.get());
14411445
}
14421446

14431447
/**

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

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import test.baeldung.doublecolon.Computer;
2020
import test.baeldung.doublecolon.MacbookPro;
2121

22+
import java.awt.BorderLayout;
2223
import java.awt.Color;
24+
import java.awt.Dimension;
2325
import java.awt.event.ActionEvent;
2426
import java.util.concurrent.CompletableFuture;
2527
import java.util.concurrent.CompletionStage;
@@ -31,6 +33,7 @@
3133
import java.util.concurrent.TimeUnit;
3234
import java.util.function.Supplier;
3335

36+
import javax.swing.BoxLayout;
3437
import javax.swing.JButton;
3538
import javax.swing.JFrame;
3639
import javax.swing.SwingUtilities;
@@ -40,26 +43,72 @@ public class Test_Future extends JFrame {
4043
Executor executor = (Runnable r) -> {
4144
new Thread(r).start();
4245
};
43-
private JButton button;
44-
46+
private JButton b1, b2;
47+
4548
public Test_Future() {
46-
setVisible(true);
47-
setBounds(500, 300, 400, 300);
49+
setLocation(400,200);
4850
setDefaultCloseOperation(EXIT_ON_CLOSE);
49-
button = new JButton("PRESS ME");
50-
button.addActionListener((ActionEvent e) -> {
51-
btnAction();
51+
b1 = new JButton("fixed");
52+
b1.setPreferredSize(new Dimension(120,40));
53+
b1.addActionListener((ActionEvent e) -> {
54+
btnAction(b1,true);
5255
});
53-
add(button);
56+
b1.setName("b1");
57+
add(b1, BorderLayout.NORTH);
58+
b2 = new JButton("delay");
59+
b2.setPreferredSize(new Dimension(120,40));
60+
b2.addActionListener((ActionEvent e) -> {
61+
btnAction(b2,false);
62+
});
63+
add(b2, BorderLayout.SOUTH);
64+
b2.setName("b2");
65+
pack();
66+
setVisible(true);
5467
}
5568

56-
Color lastColor = null;
69+
ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
5770

58-
private void btnAction() {
59-
System.out.println("button pressed");
71+
Color lastColor, lastColor1, lastColor2;
72+
73+
int nFlash = Integer.MAX_VALUE;
74+
long t0 = 0;
6075

61-
Executors.newSingleThreadScheduledExecutor().schedule(() -> {
62-
button.setForeground(lastColor = (lastColor == Color.red ? Color.blue : Color.red));
76+
private void btnAction(JButton button, boolean isFixed) {
77+
System.out.println("button pressed");
78+
if (nFlash < 20 && (button == b1 ? lastColor1 : lastColor2) != null)
79+
return;
80+
nFlash = 0;
81+
t0 = 0;
82+
Runnable r = new Runnable() {
83+
84+
@Override
85+
public void run() {
86+
if (t0 == 0)
87+
t0 = System.currentTimeMillis();
88+
System.out.println(button.getName() + " " + nFlash + " " + ((System.currentTimeMillis() - t0) / 1000.));
89+
if (nFlash++ >= 20) {
90+
System.out.println("done");
91+
lastColor1 = lastColor2 = null;
92+
exec.shutdown();
93+
} else {
94+
Color lc = (button == b1 ? lastColor1 : lastColor2);
95+
lc = (lc == Color.green ? Color.blue : Color.green);
96+
button.setForeground(lc);
97+
if (button == b1)
98+
lastColor1 = lc;
99+
else
100+
lastColor2 = lc;
101+
}
102+
}
103+
104+
};
105+
if (isFixed)
106+
exec.scheduleAtFixedRate(r, 2000, 500, TimeUnit.MILLISECONDS);
107+
else
108+
exec.scheduleWithFixedDelay(r, 2000, 500, TimeUnit.MILLISECONDS);
109+
110+
exec.schedule(() -> {
111+
button.setBackground(lastColor = (lastColor == Color.gray ? Color.lightGray : Color.gray));
63112
System.out.println("task complete");
64113
}, 3000, TimeUnit.MILLISECONDS);
65114

0 commit comments

Comments
 (0)