質問するログイン新規登録

回答編集履歴

1

実装を追記

2020/01/29 09:47

投稿

xebme
xebme

スコア1109

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()が複雑になりバグの多いコードになると思います。とはいえ、このコードはあくまでも参考にすぎません。バグがあるかもしれないし、他の実装方法も考えられるでしょう。