Como funciona o Java assíncrono? método assíncrono não parece funcionar de forma assíncrona

Tom:

Usando Java 8.

Eu tenho uma classe Logger que chama um API sempre que ele precisa para log algo. Percebi que, se a API é de alguma forma mal configurado, ou a API simplesmente não responder, minha ação log leva um lote awefull de tempo.

Exemplo de log síncrono

public void debug(String message) {
    MDC.clear();
    MDC.put(SOME_KEY, "SOME_VALUE");
    super.debug(message);
    MDC.clear();
}

Eu era capaz de identificar que o problema é aqui, porque se eu apenas comentário tudo e parar o registo ou fazer qualquer coisa, tudo corre tão rápido como deveria:

public void debug(String message) {
    //     MDC.clear();
    //     MDC.put(SOME_KEY, "SOME_VALUE");
    //     super.debug(message);
    //     MDC.clear();
}

Então eu pensei para fazer esta uma chamada assíncrona, já que eu não me importo se ele está conectado de forma síncrona:

public void debug(String message) {
    CompletableFuture.runAsync(() -> {
        MDC.clear();
        MDC.put(SOME_KEY, "SOME_VALUE");
        super.debug(message);
        MDC.clear();
    });
}

Mas esta chamada assíncrona é tão ruim, o desempenho sábio para meu aplicativo principal, como a chamada síncrona. O que estou perdendo ?

Konrad Hoffner:

Seu problema é que você não fornecer um executor. Isto pode causar Java para fornecê-lo com menos fios do que você tem atualmente aguardando chamadas de depuração, o que significa que você ainda obter algum bloqueio. No meu Intel Core i7-4790 com 4 núcleos e hyperthreading em Java 8, eu parecem ter 7 threads em execução ao mesmo tempo (número de CPUs lógicas - 1 para o segmento principal). Você pode corrigir isso através do fornecimento de um número ilimitado de tópicos usando um pool de threads em cache:

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);
    }
}

Veja o exemplo acima, que imprime "concluído" 100 vezes. Se você remover o exparâmetro, ele irá imprimir muito menos.

No entanto, a causa subjacente das chamadas de depuração lentos ainda pode precisar de ser corrigido, pois isso pode preencher a sua memória se é uma tarefa longa em execução.

Veja também: ( https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html ):

Todos os métodos assíncronos sem um argumento Executor explícito são realizadas utilizando o ForkJoinPool.commonPool () (a menos que ele não suporta um nível de paralelismo de pelo menos dois, nesse caso, um novo segmento é criado para executar cada tarefa). [...]

Acho que você gosta

Origin http://43.154.161.224:23101/article/api/json?id=187132&siteId=1
Recomendado
Clasificación