Javaの8を使用しました。
私はそれが何かをログに記録する必要があるときにAPIを呼び出すLoggerクラスを持っています。私はAPIは何とかひどく設定されている、またはAPIだけで応答しない場合、私のログアクションは、時間のawefullがかかることに気づきました。
同期ロギングの例:
public void debug(String message) {
MDC.clear();
MDC.put(SOME_KEY, "SOME_VALUE");
super.debug(message);
MDC.clear();
}
私は問題がここにあることを突き止めることができたので、もし私だけのコメントはすべて、ストップログか何かをやって、それが必要の速さですべて実行されます:
public void debug(String message) {
// MDC.clear();
// MDC.put(SOME_KEY, "SOME_VALUE");
// super.debug(message);
// MDC.clear();
}
それが同期ログに記録されますのであれば、私は気にしないので、この非同期呼び出しを行うために考えました:
public void debug(String message) {
CompletableFuture.runAsync(() -> {
MDC.clear();
MDC.put(SOME_KEY, "SOME_VALUE");
super.debug(message);
MDC.clear();
});
}
しかし、この非同期呼び出しは同期呼び出しとして、ちょうど私のメインのアプリケーションのための賢明悪い、パフォーマンスのとおりです。私は何をしないのですか?
あなたの問題は、エグゼキュータを提供しないことです。これは、Javaは、あなたが現在あなたがまだいくつかのブロックを得ることを意味し、デバッグのコールを、待っているよりも少ないスレッドを提供することがあります。Javaの8の4つのコアとハイパースレッディングと私のインテルCore i7-4790で、私は同じ時間( - 1メインスレッドの数の論理CPU)で実行されている7つのスレッドを得るように見えます。あなたは、キャッシュされたスレッドプールを使用してスレッドを無制限に供給することによってこの問題を解決することができます。
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class Test
{
public static void main(String[] args) throws InterruptedException
{
Executor ex = Executors.newCachedThreadPool();
for(int i=0;i<100;i++)
{
CompletableFuture.runAsync(() -> {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
throw new IllegalStateException(e);
}
System.out.println("completed");
},ex);
}
TimeUnit.SECONDS.sleep(2);
}
}
100回「完了」印刷し、上記の例を参照してください。あなたが削除する場合はex
、パラメータを、それははるかに少ない印刷されます。
しかし、低速のデバッグコールの根本的な原因は、まだそれが長期実行中のタスクであれば、これはあなたの記憶を埋めることとして固定する必要があるかもしれません。
参照してください:(https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html):
(それが、その場合には、新しいスレッドが各タスクを実行するために作成された少なくとも二つの並列度を、サポートしていない限り)明示的なキュータ引数なしですべての非同期メソッドはForkJoinPool.commonPool()を使用して実行されます。[...]