-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCallableAndFuture.java
More file actions
144 lines (130 loc) · 5.06 KB
/
Copy pathCallableAndFuture.java
File metadata and controls
144 lines (130 loc) · 5.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package Phase7_Concurrency.Multithreading;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
/**
* Callable<V> and Future<V>
* -------------------------
* Runnable is great when the work has NO RETURN VALUE and never throws
* checked exceptions. When you need a RESULT, use:
* <p>
*
* @FunctionalInterface
* public interface Callable<V> {
* V call() throws Exception;
* }
* <p>
*
* Submit it to an ExecutorService and you get a Future<V>:
* <p>
*
* Future<V> f = executor.submit(callable);
* V result = f.get(); // blocks until ready
* <p>
*
* Future contract
* ---------------
* get() - block until done; throw if task failed.
* get(time, unit) - block up to a timeout (TimeoutException).
* cancel(boolean mayInterrupt) - request cancellation. If true and the
* task is running, interrupt the worker.
* isDone() - finished normally, exceptionally, or cancelled.
* isCancelled()
* <p>
*
* What .get() throws
* ------------------
* InterruptedException - the caller was interrupted while waiting.
* ExecutionException - the task threw an exception. The cause is
* the original exception.
* CancellationException - the task was cancelled.
* TimeoutException - (timed version only) deadline passed.
* <p>
*
* FutureTask
* ----------
* A Runnable + Future. Useful when you want to run a Callable on a raw
* Thread (without an ExecutorService) and still grab the result:
* <p>
*
* FutureTask<Integer> task = new FutureTask<>(() -> 42);
* new Thread(task).start();
* int x = task.get();
* <p>
*
* Modern alternatives
* -------------------
* - CompletableFuture — composable async chains, no blocking get().
* - StructuredTaskScope (Java 21 preview) — fan-out + result handling
* as a single unit.
*/
public class CallableAndFuture {
public static void main(String[] args) throws Exception {
section("1) Callable returns a value");
Callable<Integer> square = () -> {
Thread.sleep(100);
return 7 * 7;
};
try (ExecutorService es = Executors.newFixedThreadPool(2)) {
Future<Integer> f = es.submit(square);
System.out.println("isDone before get? " + f.isDone());
int v = f.get(); // blocks
System.out.println("result = " + v + ", isDone? " + f.isDone());
section("2) Callable can throw checked exceptions");
Future<String> oops = es.submit(() -> {
if (Math.random() < 2) throw new java.io.IOException("disk gone");
return "never";
});
try {
oops.get();
} catch (ExecutionException ee) {
System.out.println("ExecutionException; cause = " + ee.getCause());
}
section("3) get(timeout) — give up after a deadline");
Future<String> slow = es.submit(() -> { Thread.sleep(500); return "done"; });
try {
slow.get(100, TimeUnit.MILLISECONDS);
} catch (TimeoutException te) {
System.out.println("timed out; cancelling");
slow.cancel(true);
}
section("4) cancel(mayInterruptIfRunning=true) — interrupt the worker");
Future<Integer> longRun = es.submit(() -> {
int sum = 0;
for (int i = 0; i < 1_000_000_000 && !Thread.currentThread().isInterrupted(); i++) {
sum += i;
}
return sum;
});
Thread.sleep(50);
boolean cancelled = longRun.cancel(true);
System.out.println("cancel requested = " + cancelled);
try { longRun.get(); }
catch (CancellationException ce) { System.out.println("got CancellationException"); }
section("5) Fan out + fan in with invokeAll");
List<Callable<Integer>> jobs = new ArrayList<>();
for (int i = 1; i <= 4; i++) {
final int n = i;
jobs.add(() -> { Thread.sleep(80); return n * n; });
}
long t0 = System.currentTimeMillis();
List<Future<Integer>> results = es.invokeAll(jobs);
int total = 0;
for (Future<Integer> r : results) total += r.get();
System.out.println("sum of squares = " + total + " in " +
(System.currentTimeMillis() - t0) + " ms (parallel ~80ms)");
}
section("6) FutureTask on a raw Thread (no ExecutorService)");
FutureTask<String> task = new FutureTask<>(() -> {
Thread.sleep(80);
return "hello from FutureTask";
});
new Thread(task, "future-task").start();
System.out.println(task.get());
section("done");
}
private static void section(String title) {
System.out.println();
System.out.println("=== " + title + " ===");
}
}