@@ -157,6 +157,8 @@ Threads and Executors
157
157
- the future is completed and the callback is attached from the same thread pool?
158
158
- [ Adding a callback to a ` CompletableFuture ` (` SettableFuture ` ) in non-async mode is justified?
159
159
] ( #cf-beware-non-async )
160
+ - [ Actions are delayed via a ` ScheduledExecutorService ` rather than ` Thread.sleep() ` ?
161
+ ] ( #no-sleep-schedule )
160
162
161
163
Parallel Streams
162
164
- [ Parallel Stream computation takes more than 100us in total?] ( #justify-parallel-stream-use )
@@ -1172,6 +1174,8 @@ execution mode* (via methods like `thenAccept()`, `thenApply()`, `handle()`, etc
1172
1174
inadvertently lead to performing them in ` ForkJoinPool ` from where the future may be completed: see
1173
1175
[ TE.7] ( #cf-beware-non-async ) .
1174
1176
1177
+ ` Thread.sleep() ` is a blocking operation.
1178
+
1175
1179
This advice should not be taken too far: occasional transient IO (such as that may happen during
1176
1180
logging) and operations that may rarely block (such as ` ConcurrentHashMap.put() ` calls) usually
1177
1181
shouldn’t disqualify all their callers from execution in a ` ForkJoinPool ` or in a parallel ` Stream ` .
@@ -1246,6 +1250,22 @@ See also the Javadoc for [`ListenableFuture.addListener()`](
1246
1250
https://guava.dev/releases/28.1-jre/api/docs/com/google/common/util/concurrent/ListenableFuture.html#addListener-java.lang.Runnable-java.util.concurrent.Executor-
1247
1251
) describing this problem.
1248
1252
1253
+ <a name =" no-sleep-schedule " ></a >
1254
+ [ #] ( #no-sleep-schedule ) TE.8. ** A task or action is executed with a delay via a
1255
+ [ ` ScheduledExecutorService ` ] (
1256
+ https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ScheduledExecutorService.html )
1257
+ rather than by calling ` Thread.sleep() ` before performing the work** or submitting the task to
1258
+ an executor? ` ScheduledExecutorService ` allows to execute many such tasks on a small number of
1259
+ threads, while the approach with ` Thread.sleep ` requires a dedicated thread for every delayed
1260
+ action. Sleeping in the context of an unknown executor (if there is insufficient * concurrent access
1261
+ documentation* for the method, as per [ Dc.1] ( #justify-document ) , or if this is a
1262
+ concurrency-agnostic library method) before submitting the task to an executor is also bad: the
1263
+ context executor may not tolerate blocking calls such as ` Thread.sleep ` , see
1264
+ [ TE.4] ( #fjp-no-blocking ) for details.
1265
+
1266
+ This item equally applies to scheduling one-shot and recurrent delayed actions, there are methods
1267
+ for both scenarios in ` ScheduledExecutorService ` .
1268
+
1249
1269
### Parallel Streams
1250
1270
1251
1271
<a name =" justify-parallel-stream-use " ></a >
0 commit comments