回答編集履歴
1
実装を追記
answer
CHANGED
@@ -4,4 +4,59 @@
|
|
4
4
|
|
5
5
|
スレッドで先読みを実行するほうが自然ではないでしょうか。[How to timeout a thread](https://stackoverflow.com/questions/2275443/how-to-timeout-a-thread)
|
6
6
|
- 2秒以内に先読みの結果が得られれば利用する
|
7
|
-
- 2秒待っても先読みの結果が返らなければスレッドを破棄する
|
7
|
+
- 2秒待っても先読みの結果が返らなければスレッドを破棄する
|
8
|
+
|
9
|
+
**先読処理の実装**
|
10
|
+
|
11
|
+
自分で先読処理を実装するとしたらどうするか。質問に直接答えようとしない興味本位のコードです。
|
12
|
+
- ExecutorServiceフレームワークを使用する
|
13
|
+
- 先読処理はスレッドで実装する(Future,Callableを使用する)
|
14
|
+
- タイムアウト時間を指定する
|
15
|
+
- 先読処理がタイムアウト時間を超過するならキャンセルする
|
16
|
+
|
17
|
+
|
18
|
+
```Java
|
19
|
+
import java.util.concurrent.CancellationException;
|
20
|
+
import java.util.concurrent.ExecutionException;
|
21
|
+
import java.util.concurrent.Executors;
|
22
|
+
import java.util.concurrent.Future;
|
23
|
+
import java.util.concurrent.ScheduledExecutorService;
|
24
|
+
import java.util.concurrent.TimeUnit;
|
25
|
+
import java.util.concurrent.TimeoutException;
|
26
|
+
|
27
|
+
static String wait4LookaheadSearch(final int timeout) {
|
28
|
+
|
29
|
+
String result = "none.";
|
30
|
+
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
|
31
|
+
|
32
|
+
try {
|
33
|
+
// 先読み処理を実行する。
|
34
|
+
final Future<String> handler = executor.submit(
|
35
|
+
() -> {
|
36
|
+
System.out.println("look-ahead search ... ");
|
37
|
+
try {
|
38
|
+
Thread.sleep((int) (Math.random() * timeout * 2));
|
39
|
+
} catch (InterruptedException e) {
|
40
|
+
throw e;
|
41
|
+
}
|
42
|
+
if (Thread.interrupted()) throw new InterruptedException();
|
43
|
+
return "the best hand."; // 先読み結果を返す。
|
44
|
+
});
|
45
|
+
|
46
|
+
try { // 最適解が見つかるか、タイムアウトするまで待つ。
|
47
|
+
result = handler.get(timeout, TimeUnit.MILLISECONDS);
|
48
|
+
} catch (TimeoutException e) { // タイムアウトした
|
49
|
+
if (!handler.isDone()) {
|
50
|
+
handler.cancel(true); // キャンセルする(強制割り込みをかける)
|
51
|
+
}
|
52
|
+
result = "timeout.";
|
53
|
+
} catch (ExecutionException | InterruptedException | CancellationException e) {
|
54
|
+
result = "failed."; // 実行失敗
|
55
|
+
}
|
56
|
+
} finally {
|
57
|
+
executor.shutdownNow();
|
58
|
+
}
|
59
|
+
return result;
|
60
|
+
}
|
61
|
+
```
|
62
|
+
使い方は、"main"スレッドを2秒スリープする代わりに`wait4LookaheadSearch(2000);`とします。Timerを使うとmain()が複雑になりバグの多いコードになると思います。とはいえ、このコードはあくまでも参考にすぎません。バグがあるかもしれないし、他の実装方法も考えられるでしょう。
|