1
+ /* Copyright (c) 2024 LibJ
2
+ *
3
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ * of this software and associated documentation files (the "Software"), to deal
5
+ * in the Software without restriction, including without limitation the rights
6
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ * copies of the Software, and to permit persons to whom the Software is
8
+ * furnished to do so, subject to the following conditions:
9
+ *
10
+ * The above copyright notice and this permission notice shall be included in
11
+ * all copies or substantial portions of the Software.
12
+ *
13
+ * You should have received a copy of The MIT License (MIT) along with this
14
+ * program. If not, see <http://opensource.org/licenses/MIT/>.
15
+ */
16
+
17
+ package org .libj .util .concurrent ;
18
+
19
+ import java .util .concurrent .Callable ;
20
+ import java .util .concurrent .Delayed ;
21
+ import java .util .concurrent .ScheduledExecutorService ;
22
+ import java .util .concurrent .ScheduledFuture ;
23
+ import java .util .concurrent .TimeUnit ;
24
+
25
+ /**
26
+ * A {@link ScheduledExecutorService} that executes its submitted tasks synchronously in the current thread.
27
+ */
28
+ public class SynchronousScheduledExecutorService extends SynchronousExecutorService implements ScheduledExecutorService {
29
+ static class SynchronousScheduledFuture <T > extends SynchronousFuture <T > implements ScheduledFuture <T > {
30
+ private final long delay ;
31
+ private final TimeUnit timeUnit ;
32
+
33
+ SynchronousScheduledFuture (final T result , final long delay , final TimeUnit timeUnit ) {
34
+ super (result );
35
+ this .delay = delay ;
36
+ this .timeUnit = timeUnit ;
37
+ }
38
+
39
+ @ Override
40
+ public int compareTo (final Delayed o ) {
41
+ int c = TimeUnits .compare (delay , timeUnit , o .getDelay (TimeUnit .MILLISECONDS ), TimeUnit .MILLISECONDS );
42
+ if (c != 0 )
43
+ return c ;
44
+
45
+ c = TimeUnits .compare (delay , timeUnit , o .getDelay (TimeUnit .MICROSECONDS ), TimeUnit .MICROSECONDS );
46
+ if (c != 0 )
47
+ return c ;
48
+
49
+ return TimeUnits .compare (delay , timeUnit , o .getDelay (TimeUnit .NANOSECONDS ), TimeUnit .NANOSECONDS );
50
+ }
51
+
52
+ @ Override
53
+ public long getDelay (final TimeUnit unit ) {
54
+ return unit .convert (delay , timeUnit );
55
+ }
56
+ }
57
+
58
+ @ Override
59
+ public ScheduledFuture <?> schedule (final Runnable command , final long delay , final TimeUnit unit ) {
60
+ try {
61
+ Thread .sleep (TimeUnit .MILLISECONDS .convert (delay , unit ));
62
+ }
63
+ catch (final InterruptedException e ) {
64
+ throw new RuntimeException (e );
65
+ }
66
+
67
+ command .run ();
68
+ return new SynchronousScheduledFuture <>(null , delay , unit );
69
+ }
70
+
71
+ @ Override
72
+ public <V > ScheduledFuture <V > schedule (final Callable <V > callable , final long delay , final TimeUnit unit ) {
73
+ try {
74
+ Thread .sleep (TimeUnit .MILLISECONDS .convert (delay , unit ));
75
+ return new SynchronousScheduledFuture <>(callable .call (), delay , unit );
76
+ }
77
+ catch (final Exception e ) {
78
+ if (e instanceof RuntimeException )
79
+ throw (RuntimeException )e ;
80
+
81
+ throw new RuntimeException (e );
82
+ }
83
+ }
84
+
85
+ @ Override
86
+ public ScheduledFuture <?> scheduleAtFixedRate (final Runnable command , final long initialDelay , final long period , final TimeUnit unit ) {
87
+ try {
88
+ Thread .sleep (TimeUnit .MILLISECONDS .convert (initialDelay , unit ));
89
+ final long rateMillis = TimeUnit .MILLISECONDS .convert (period , unit );
90
+ for (long ts = System .currentTimeMillis (), sleep ;;) {
91
+ command .run ();
92
+ sleep = rateMillis - (System .currentTimeMillis () - ts );
93
+ ts = System .currentTimeMillis ();
94
+ if (sleep > 0 )
95
+ Thread .sleep (sleep );
96
+ }
97
+ }
98
+ catch (final Exception e ) {
99
+ if (e instanceof RuntimeException )
100
+ throw (RuntimeException )e ;
101
+
102
+ throw new RuntimeException (e );
103
+ }
104
+ }
105
+
106
+ @ Override
107
+ public ScheduledFuture <?> scheduleWithFixedDelay (final Runnable command , final long initialDelay , final long delay , final TimeUnit unit ) {
108
+ try {
109
+ Thread .sleep (TimeUnit .MILLISECONDS .convert (initialDelay , unit ));
110
+ final long delayMillis = TimeUnit .MILLISECONDS .convert (delay , unit );
111
+ while (true ) {
112
+ Thread .sleep (delayMillis );
113
+ command .run ();
114
+ }
115
+ }
116
+ catch (final Exception e ) {
117
+ if (e instanceof RuntimeException )
118
+ throw (RuntimeException )e ;
119
+
120
+ throw new RuntimeException (e );
121
+ }
122
+ }
123
+ }
0 commit comments