回答編集履歴

1

実装を追記

2020/01/29 09:47

投稿

xebme
xebme

スコア1083

test CHANGED
@@ -11,3 +11,113 @@
11
11
  - 2秒以内に先読みの結果が得られれば利用する
12
12
 
13
13
  - 2秒待っても先読みの結果が返らなければスレッドを破棄する
14
+
15
+
16
+
17
+ **先読処理の実装**
18
+
19
+
20
+
21
+ 自分で先読処理を実装するとしたらどうするか。質問に直接答えようとしない興味本位のコードです。
22
+
23
+ - ExecutorServiceフレームワークを使用する
24
+
25
+ - 先読処理はスレッドで実装する(Future,Callableを使用する)
26
+
27
+ - タイムアウト時間を指定する
28
+
29
+ - 先読処理がタイムアウト時間を超過するならキャンセルする
30
+
31
+
32
+
33
+
34
+
35
+ ```Java
36
+
37
+ import java.util.concurrent.CancellationException;
38
+
39
+ import java.util.concurrent.ExecutionException;
40
+
41
+ import java.util.concurrent.Executors;
42
+
43
+ import java.util.concurrent.Future;
44
+
45
+ import java.util.concurrent.ScheduledExecutorService;
46
+
47
+ import java.util.concurrent.TimeUnit;
48
+
49
+ import java.util.concurrent.TimeoutException;
50
+
51
+
52
+
53
+ static String wait4LookaheadSearch(final int timeout) {
54
+
55
+
56
+
57
+ String result = "none.";
58
+
59
+ ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
60
+
61
+
62
+
63
+ try {
64
+
65
+ // 先読み処理を実行する。
66
+
67
+ final Future<String> handler = executor.submit(
68
+
69
+ () -> {
70
+
71
+ System.out.println("look-ahead search ... ");
72
+
73
+ try {
74
+
75
+ Thread.sleep((int) (Math.random() * timeout * 2));
76
+
77
+ } catch (InterruptedException e) {
78
+
79
+ throw e;
80
+
81
+ }
82
+
83
+ if (Thread.interrupted()) throw new InterruptedException();
84
+
85
+ return "the best hand."; // 先読み結果を返す。
86
+
87
+ });
88
+
89
+
90
+
91
+ try { // 最適解が見つかるか、タイムアウトするまで待つ。
92
+
93
+ result = handler.get(timeout, TimeUnit.MILLISECONDS);
94
+
95
+ } catch (TimeoutException e) { // タイムアウトした
96
+
97
+ if (!handler.isDone()) {
98
+
99
+ handler.cancel(true); // キャンセルする(強制割り込みをかける)
100
+
101
+ }
102
+
103
+ result = "timeout.";
104
+
105
+ } catch (ExecutionException | InterruptedException | CancellationException e) {
106
+
107
+ result = "failed."; // 実行失敗
108
+
109
+ }
110
+
111
+ } finally {
112
+
113
+ executor.shutdownNow();
114
+
115
+ }
116
+
117
+ return result;
118
+
119
+ }
120
+
121
+ ```
122
+
123
+ 使い方は、"main"スレッドを2秒スリープする代わりに`wait4LookaheadSearch(2000);`とします。Timerを使うとmain()が複雑になりバグの多いコードになると思います。とはいえ、このコードはあくまでも参考にすぎません。バグがあるかもしれないし、他の実装方法も考えられるでしょう。