¿Cómo funciona Java asíncrono? método asíncrono no parece funcionar de forma asíncrona

tom:

Uso de Java 8.

Tengo una clase Logger que llama a una API cada vez que necesita para registrar algo. Me di cuenta de que si la API de alguna manera está mal configurado, o la API simplemente no responde, mi acción de registro recibe una gran cantidad de tiempo awefull.

Ejemplo de registro síncrono:

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

Yo era capaz de señalar que el problema está aquí porque si acabo de comentar todo y parada de registro o hacer cualquier cosa, todo corre tan rápido como debería:

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

Así que pensé que hacer esto una llamada asincrónica, ya no me importa si se registra de forma sincronizada:

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

Pero esta llamada asincrónica es igual de malo, con respecto al rendimiento de mi aplicación principal, ya que la llamada sincrónica. Qué me estoy perdiendo ?

Konrad Hoffner:

Su problema es que no proporciona un ejecutor. Esto puede causar Java para proporcionar con menos hilos de lo que actualmente haya llamadas en espera de depuración, lo que significa que todavía conseguir un poco de bloqueo. En mi Intel Core i7-4790 con 4 núcleos y 8 hyperthreading en Java, que parecen llegar 7 subprocesos que se ejecutan al mismo tiempo (número lógico CPU - 1 para el hilo principal). Puede solucionar este problema mediante el suministro de un número ilimitado de hilos utilizando un grupo de subprocesos en caché:

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

Ver el ejemplo anterior, que imprime "completado" 100 veces. Si se quita el exparámetro, se imprimirá mucho menos.

Sin embargo todavía puede necesitar la causa subyacente de llamadas de depuración lenta para ser fijada ya que esto puede llenar su memoria si se trata de una tarea larga duración.

Ver también: ( https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html ):

Todos los métodos asincrónicos sin un argumento explícito Ejecutor se realizan utilizando el ForkJoinPool.commonPool () (a menos que no soporta un nivel de paralelismo de al menos dos, en cuyo caso, se crea un nuevo hilo para ejecutar cada tarea). [...]

Supongo que te gusta

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