Skip to content

Commit de24241

Browse files
committed
Add TE.8 about ScheduledExecutorService and Thread.sleep(), fixes #13
1 parent 3ec1afd commit de24241

File tree

1 file changed

+20
-0
lines changed

1 file changed

+20
-0
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ Threads and Executors
157157
- the future is completed and the callback is attached from the same thread pool?
158158
- [Adding a callback to a `CompletableFuture` (`SettableFuture`) in non-async mode is justified?
159159
](#cf-beware-non-async)
160+
- [Actions are delayed via a `ScheduledExecutorService` rather than `Thread.sleep()`?
161+
](#no-sleep-schedule)
160162

161163
Parallel Streams
162164
- [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
11721174
inadvertently lead to performing them in `ForkJoinPool` from where the future may be completed: see
11731175
[TE.7](#cf-beware-non-async).
11741176

1177+
`Thread.sleep()` is a blocking operation.
1178+
11751179
This advice should not be taken too far: occasional transient IO (such as that may happen during
11761180
logging) and operations that may rarely block (such as `ConcurrentHashMap.put()` calls) usually
11771181
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()`](
12461250
https://guava.dev/releases/28.1-jre/api/docs/com/google/common/util/concurrent/ListenableFuture.html#addListener-java.lang.Runnable-java.util.concurrent.Executor-
12471251
) describing this problem.
12481252

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+
12491269
### Parallel Streams
12501270

12511271
<a name="justify-parallel-stream-use"></a>

0 commit comments

Comments
 (0)