これは、コーディングの問題を示している可能性があります。FutureTask
コードは、まだ実行されていないa の完了を待ちます。
デモンストレーション用のスニペットの下を見つけます
Future.java
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
public class Future {
public static void main(String[] args) throws Exception {
FutureTask<String> future = new FutureTask<>(
new Callable<String>() {
@Override
public String call() throws InterruptedException {
return "foo";
}
});
String get = future.get(30, TimeUnit.SECONDS);
System.out.println("get = " + get);
}
}
セッション 1 で実行
javac Future.java
java Future
セッション 2 で実行
$ jps
...
12345 Future
jstack -l 12345 > jstack.12345.log
注: 12345
は実行中のjava Future
プロセスの PID です
jstack.12345.log の内容
"main" #1 prio=5 os_prio=0 tid=0x000000000273b000 nid=0x2b24 waiting on condition [0x0000000002abf000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000781973910> (a java.util.concurrent.FutureTask)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:426)
at java.util.concurrent.FutureTask.get(FutureTask.java:204)
at Future.main(Future.java:19)
編集投稿されたコード スニペットに基づいて、説明されている状況は非常に簡単に発生する可能性があります。Executor.executeの javadoc を参照
将来のある時点で指定されたコマンドを実行します。
at some time in the future
これは、 の呼び出し直後ではないexecute
ことを意味します。task.get(...)
そのため、タスクが実際に実行される前に行に到達する可能性があります。また、スレッド プールが同時にスレッドを実行できない場合もありますnumberOfThreads()
。
デモ用の小さな例 (前述と同じコマンドを実行します)。一度に 1 つのタスクのみを実行するスレッド プールを作成します。そのプールに 2 つのタスクを割り当てます。両方のタスクを呼び出した直後にexecutor.execute(..)
、2 番目のタスクの結果を待ちます。最初のタスクは長時間実行されるタスクであるため、発見した状況に踏み込みます。
Future.java
public class Future {
public static void main(String[] args) throws Exception {
FutureTask<String> future1 = new FutureTask<>(
() -> {
System.out.println("future1");
TimeUnit.SECONDS.sleep(50);
return "finished future1";
});
FutureTask<String> future2 = new FutureTask<>(
() -> {
System.out.println("future2");
return "finished future2";
});
ExecutorService executor = Executors.newFixedThreadPool(1);
executor.execute(future1);
executor.execute(future2);
String get = future2.get(30, TimeUnit.SECONDS);
}
}
jstack.12345.log の内容
"pool-1-thread-1" #9 prio=5 os_prio=0 tid=0x00007ff50811c000 nid=0x5a5c waiting on condition [0x00007ff4e7365000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:340)
at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
at concurrent.Future$1.call(Future.java:19)
at concurrent.Future$1.call(Future.java:15)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
"main" #1 prio=5 os_prio=0 tid=0x00007ff50800a000 nid=0x5a4d waiting on condition [0x00007ff50e314000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000ec03dda8> (a java.util.concurrent.FutureTask)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:426)
at java.util.concurrent.FutureTask.get(FutureTask.java:204)
at concurrent.Future.main(Future.java:36)
pool-1-thread-1
- 現在スリープしているダンプですfuture1
(長時間実行されるタスクをシミュレートするため)。
main
- は のダンプで、実際にはまだ開始されていないfuture2.get(30, TimeUnit.SECONDS)
の結果を待ちます。future2