Java异步是如何工作的?异步方法似乎不是异步运行的

Java异步是如何工作的?异步方法似乎不是异步运行的,java,performance,asynchronous,Java,Performance,Asynchronous,使用Java8 我有一个Logger类,它在需要记录某些内容时调用API。我意识到,如果API配置不当,或者API无法响应,那么我的日志操作将花费大量时间 同步日志记录示例: public void debug(String message) { MDC.clear(); MDC.put(SOME_KEY, "SOME_VALUE"); super.debug(message); MDC.clear(); } 我能够指出问题出在这里,因为如果我只是评论所有内容,

使用Java8

我有一个Logger类,它在需要记录某些内容时调用API。我意识到,如果API配置不当,或者API无法响应,那么我的日志操作将花费大量时间

同步日志记录示例:

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为您提供的线程少于您当前等待的调试调用,这意味着您仍然会遇到一些阻塞。在我的4核Intel Core i7-4790和Java 8上的超线程上,我似乎可以同时运行7个线程(主线程的逻辑CPU数为-1)。您可以通过使用缓存线程池提供无限数量的线程来解决此问题:

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);
    }
}
import java.util.concurrent.CompletableFuture;
导入java.util.concurrent.Executor;
导入java.util.concurrent.Executors;
导入java.util.concurrent.TimeUnit;
公开课考试
{
公共静态void main(字符串[]args)引发InterruptedException
{
Executor ex=Executors.newCachedThreadPool();
对于(int i=0;i{
试一试{
时间单位。秒。睡眠(1);
}捕捉(中断异常e){
抛出新的非法状态异常(e);
}
系统输出打印项次(“完成”);
},ex);
}
时间单位。秒。睡眠(2);
}
}
请参见上面的示例,该示例打印“已完成”100次。如果删除
ex
参数,它的打印量将大大减少

但是,可能仍然需要修复调试调用缓慢的根本原因,因为如果是长时间运行的任务,这可能会占用您的内存

另见:():

没有显式执行器参数的所有异步方法都是 使用ForkJoinPool.commonPool()执行(除非它没有 支持至少两个并行级别,在这种情况下,新的 创建线程以运行每个任务)。[……]


我会尝试,我也会修复根本原因,但我想首先修复这个问题,因为如果远程日志API不知何故出现几秒钟的故障,我不希望用户受到问题的影响:)它工作正常,非常感谢,我可能已经找了很久了