私は、セマフォーなどを使用してJavaでコードの特定のセクションを実行できるスレッドの数を制限する方法を探しています。Javaでコードの特定のセクションを実行するスレッドの数を制限する最良の方法は?
Google Guava RateLimiterと似たようなものを探していましたが、1秒あたりの呼び出し数を制限する代わりに、コードのクリティカルセクションを実行するスレッド数を制限する必要があります。
私たちが使用している特定のライブラリには問題がありますので、すぐに回避策を探しています。
私は、セマフォーなどを使用してJavaでコードの特定のセクションを実行できるスレッドの数を制限する方法を探しています。Javaでコードの特定のセクションを実行するスレッドの数を制限する最良の方法は?
Google Guava RateLimiterと似たようなものを探していましたが、1秒あたりの呼び出し数を制限する代わりに、コードのクリティカルセクションを実行するスレッド数を制限する必要があります。
私たちが使用している特定のライブラリには問題がありますので、すぐに回避策を探しています。
これはjava.util.concurrent.Semaphore
を行うように設計された、まさにです。あなたはそのようなSemaphore
を作成:
final int MAX_NOF_THREADS = 5;
final Semaphore mySemaphore = new Semaphore(MAX_NOF_THREADS);
その後、あなたがしたい重要な領域について:
try {
mySemaphore.aquire(); // This will hang until there is a vacancy
do_my_critical_stuff();
} finally {
mySemaphore.release();
}
...そのような単純なよう。
私は 'Semaphore'sに完全に同意します。このタスクの最初の選択肢になるはずです。ただし、言及する価値のあるものが1つあります。技術的には、1つのスレッドで複数の取得を行うことができます。つまり、いくつかの論理的なエラー(例えば、意図しない再帰)は、スレッドの不十分な使用やデッドロックの原因となる可能性があります。しかし、慎重に使用される場合、それらはここでは適切なツールです。 –
注意しておけばSemaphore
が最適です(@ Bexの回答をご覧ください)。ExecutorService
も使用できます。ちょうどあなたがCallable
タスクに無制限の同時アクセスから保護し、エグゼキュータのサービスにこのようなタスクを提出したいコードの一部ラップ:ExecutorService
で
// Task that will be executed
public class MyTask implements Callable<Void> {
@Override
public Void call() {
// Do the work here
return null;
}
}
// Service to execute tasks in no more than 5 parallel threads
// Cache it after creation and use when you need to execute a task
int maxThreadsCount = 5;
ExecutorService executor = Executors.newFixedThreadPool(maxThreadsCount);
// Execute a task. It will wait if all 5 threads are busy right now.
executor.submit(new MyTask());
をあなたもRunnable
代わりのCallable
、invokeAll()
の代わりに使用することができますexecute
、タスクの完了を待って、タスクをキャンセルし、それらから値を返し、その他の便利なことをしてください。
のJava 8はそれを簡単になり、あなたの代わりにタスククラスを定義するラムダを使用することができます。
executor.submit(() -> {
// Do the work here
});
何かを覚えておいてください。Executorsファクトリは、無制限のジョブキューによってサポートされるExecutorService実装を構築します。実行中のジョブの実行頻度や実行時間によっては、システムに悪影響を与える可能性があります。場合によっては、メモリにキューされたジョブの数が原因でアプリケーションを停止させることがあります。そのような場合は、バインドされた作業キューとカスタム** RejectedExecutionHandler **を使用して、独自の** ThreadPoolExecutor **を作成する価値があります。コードのセクションがどのように重要であるかを見ると、おそらく無制限のバージョンが必要です。その影響に気をつけてください。 – Jeremiah
java.util.concurrent.Semaphoreを使用できないのはなぜですか? –