¿Por qué cuando no uso el estilo de código "lambda método de referencia" en bloque estático provocará estancamiento?

ACBingo:

PD: Lo siento por mi pobre English.I no puede describir el problema con claridad. :(

Cuando yo no uso el estilo de código "lambda referencia del método" en el bloque estático, como:

static{
map.keySet().parallelStream().forEach(e -> {
            System.out.println(e);
        });
}

a continuación, el programa que se ejecuta siempre, nunca se detiene.

Pero cuando cambio el código de

static{
map.keySet().parallelStream().forEach(System.out::println);
}

a continuación, el programa gone.The error puede terminar inmediatamente.

Basta con mirar directamente en el código por favor, Ya he intentado simplificar el código en lo que pueda.

public class BugSimulate {

    static {
        init();
    }

    private static void init() {
        Map<Integer, String> map = new HashMap<>();

        int i = 0;
        map.put(++i, "1");
        map.put(++i, "1");
        map.put(++i, "1");
        map.put(++i, "1");
        map.put(++i, "1");
        map.put(++i, "1");
        map.put(++i, "1");
        map.put(++i, "1");
        map.put(++i, "1");

        // running forever
        map.keySet().parallelStream().forEach(e -> {
            System.out.println(e);
        });

        // finish immediately
        //        map.keySet().parallelStream().forEach(System.out::println);
    }

    @Test
    public void test() {
        new BugSimulate();
    }
}

introducir descripción de la imagen aquí

pero cuando cambio el código lambda

e -> {System.out.println(e);}

a

System.out::println

el programa acabado inmediatamente

introducir descripción de la imagen aquí

O cambio parallelStream () para flujo normal (), los insectos han ido.

O elimino los bloques estáticos, insectos ido demasiado.

Mi versión JDK es 1.8.0_202

Y la versión del sistema operativo MacOS es 10.14.5

chengpohi :

Interesting Question: This question is similar with Class Loading with Static Block Competition Cause Deadlock,

but for this issue, it's caused by when use e -> {System.out.println(e);} after compiling, it will generate an synthetic method: anonymous static private method for this, as:

  // access flags 0x100A
  private static synthetic lambda$init$0(Ljava/lang/Integer;)V
   L0
    LINENUMBER 27 L0
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ALOAD 0
    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V
   L1
    LINENUMBER 28 L1
    RETURN
   L2
    LOCALVARIABLE e Ljava/lang/Integer; L0 L2 0
    MAXSTACK = 2
    MAXLOCALS = 1

this synthetic method: private static method is generated by e -> {System.out.println(e);} compile.

also it's similar equal to:

static {
    init();
}

private static void init() {
    Map<Integer, String> map = new HashMap<>();

    int i = 0;
    map.put(++i, "1");
    ***
    Thread foo = new Thread() {
        @Override
        public void run() {
            print(map.keySet().iterator().next()); //try access the private method, this cause a competition with **Class Initializer** and **static block**
        }
    };

    foo.start();
    try {
        foo.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
//equal to e -> {System.out.println(e);}
private static void print(int t) {
    System.out.println(t);
}

con el fin de Carga Clase con estático Competencia Bloque causar interbloqueo este post explicación: cuando init clase BugSimulate , se invocará static blocken primer lugar, pero ya que se trata de utilizar parallelStream y tratar de invocar el método anónimo privada generada, esto causó un concurso con el inicializador de la clase , por lo que finalmente es punto muerto.

Competencia

Supongo que te gusta

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