私は次のコードを実行すると:bare ThreadPoolExecutorを使用してMoreExecutors.newDirectExecutorService()の動作を取得するにはどうすればよいですか?
package foo.trials;
import com.google.common.util.concurrent.MoreExecutors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class DirectExecutorService {
private static final Logger logger_ = LoggerFactory.getLogger(DirectExecutoService.class);
public static void main(String[] args) {
boolean useGuava = true;
final ExecutorService directExecutorService;
if (useGuava) {
directExecutorService = MoreExecutors.newDirectExecutorService();
} else {
directExecutorService = new ThreadPoolExecutor(
0, 1, 0, TimeUnit.DAYS,
new SynchronousQueue<Runnable>(),
new ThreadPoolExecutor.CallerRunsPolicy());
directExecutorService.submit(new BlockingCallable());
}
Future<Boolean> future = directExecutorService.submit(new MyCallable());
try {
logger_.info("Result: {}", future.get());
} catch (InterruptedException e) {
logger_.error("Unexpected: Interrupted!", e);
} catch (ExecutionException e) {
logger_.error("Unexpected: Execution exception!", e);
}
logger_.info("Exiting...");
}
static class MyCallable implements Callable<Boolean> {
static final Random _random = new Random();
@Override
public Boolean call() throws Exception {
logger_.info("In call()");
return _random.nextBoolean();
}
}
static class BlockingCallable implements Callable<Boolean> {
Semaphore semaphore = new Semaphore(0);
@Override
public Boolean call() throws Exception {
semaphore.acquire(); // this will never succeed.
return true;
}
}
}
を、私は、実行のすべてがmain
のスレッドで起こる次の出力
13:36:55.960 [main] INFO a.t.DirectExecutoService - In call()
13:36:55.962 [main] INFO a.t.DirectExecutoService - Result: true
13:36:55.963 [main] INFO a.t.DirectExecutoService - Exiting...
注意を取得します。特に、呼び出し可能な呼び出しのgetは、呼び出し元のスレッドにディスパッチされます。もちろん、これはMoreExecutors.newDirectExecutorService()
から驚くことはありません。
変数useGuava
をfalse
に設定すると、同様の結果が得られます。
13:45:14.264 [main] INFO a.t.DirectExecutoService - In call()
13:45:14.267 [main] INFO a.t.DirectExecutoService - Result: true
13:45:14.268 [main] INFO a.t.DirectExecutoService - Exiting...
しかし、私は次の行に
directExecutorService.submit(new BlockingCallable());
をコメントアウトした場合、私は次の出力を取得します。
13:37:27.355 [pool-1-thread-1] INFO a.t.DirectExecutoService - In call()
13:37:27.357 [main] INFO a.t.DirectExecutoService - Result: false
13:37:27.358 [main] INFO a.t.DirectExecutoService - Exiting...
1は、呼び出し可能なの呼び出しが別のスレッドpool-1-thread-1
で行わ見ることができるように。なぜこのようなことが起こるのか説明できると思います。おそらくスレッドプールは利用可能なスレッドを最大1つ持つことができるので、第1呼び出しはBlockingCallable
で消費された余分なスレッドにディスパッチされます。
ExecutorService
私はどのようにしてDirectExecutorService
を実行するのですか?人工的に終了しない呼び出し可能なスレッドを人工的に焼く必要はありませんか?
なぜ私はこれを求めていますか?
- 私はguavaをバージョン11.0で使用するコードベースを使用しています。私はそれを17.0+にアップグレードすることを避ける必要があります - できるならば
MoreExecutors.newDirectExecutorService()
- を提供します。 ThreadPoolExecutor
は、maxThreads
を0に設定することはできません。それが許可されていればそれは奇妙ですが、そうしてしまえば、私の問題も解決しました。- 最後には、私はこの動作に気づくことに驚いた - 私は(誤って)
CallerRunsPolicy
を使用すると、すべてのcall
Callable
すべてのsが呼び出し側のスレッドで実行させるだろうと想定していました。だから、私は自分の経験を入れてそこにハックして、誰かがこれを理解しようと燃え尽きた時間を節約できるようにしたかったのです。 :(
は1つが17.0+?
これは、ありがとうございます!アップグレードについてのポイントがよく取られます。 –