2011-10-08 7 views
12

El siguiente código Java trivial:El ejemplo simple de Java se ejecuta con 14 hilos. ¿Por qué?

public class Main { 
    public static void main(String[] args) throws InterruptedException { 
     System.out.println("Start"); 
     Thread.sleep(5000); 
     System.out.println("Done"); 
    } 
} 

ejecuta utilizando 14 hilos. Sé que hay un hilo de GC ejecutándose en segundo plano, pero ¿para qué sirven los otros? ¿Por qué hay tantos hilos? Estoy en Gentoo Linux con Java 1.6.0_26. Compilar con el compilador de Eclipse o javac no hace la diferencia (ejecutarlo en Eclipse en modo de depuración le agrega 3 hilos más, pero eso probablemente esté justificado).

+1

¿Cómo está ejecutando su código? Si está ejecutando desde un IDE, ¿podría ser que su IDE en sí mismo está escrito (y ejecutándose) en Java? – DevSolar

+3

Tengo curiosidad, ¿cómo determinas que funcione 14 hilos? – Coffee

+0

¿Qué te hace pensar que hay 14 hilos? –

Respuesta

14

Mi JVM (1.6.0_26) genera incluso más subprocesos de forma predeterminada. La mayoría tienen nombres muy descriptivos que hacen alusión a su propósito:

"Attach Listener" daemon prio=10 tid=0x0000000041426800 nid=0x2fb9 waiting on condition [0x0000000000000000] 
    java.lang.Thread.State: RUNNABLE 

"Low Memory Detector" daemon prio=10 tid=0x00007f512c07e800 nid=0x2fa3 runnable [0x0000000000000000] 
    java.lang.Thread.State: RUNNABLE 

"C2 CompilerThread1" daemon prio=10 tid=0x00007f512c07b800 nid=0x2fa2 waiting on condition [0x0000000000000000] 
    java.lang.Thread.State: RUNNABLE 

"C2 CompilerThread0" daemon prio=10 tid=0x00007f512c078800 nid=0x2fa1 waiting on condition [0x0000000000000000] 
    java.lang.Thread.State: RUNNABLE 

"Signal Dispatcher" daemon prio=10 tid=0x00007f512c076800 nid=0x2fa0 runnable [0x0000000000000000] 
    java.lang.Thread.State: RUNNABLE 

"Finalizer" daemon prio=10 tid=0x00007f512c05a000 nid=0x2f9f in Object.wait() [0x00007f512b8f7000] 
    java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    - waiting on <0x00000007c14b1300> (a java.lang.ref.ReferenceQueue$Lock) 
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118) 
    - locked <0x00000007c14b1300> (a java.lang.ref.ReferenceQueue$Lock) 
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134) 
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159) 

"Reference Handler" daemon prio=10 tid=0x00007f512c058000 nid=0x2f9e in Object.wait() [0x00007f512b9f8000] 
    java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    - waiting on <0x00000007c14b11d8> (a java.lang.ref.Reference$Lock) 
    at java.lang.Object.wait(Object.java:485) 
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116) 
    - locked <0x00000007c14b11d8> (a java.lang.ref.Reference$Lock) 

"main" prio=10 tid=0x0000000041401800 nid=0x2f94 waiting on condition [0x00007f5135735000] 
    java.lang.Thread.State: TIMED_WAITING (sleeping) 
    at java.lang.Thread.sleep(Native Method) 
    at Main.main(Main.java:5) 

"VM Thread" prio=10 tid=0x00007f512c051800 nid=0x2f9d runnable 

"GC task thread#0 (ParallelGC)" prio=10 tid=0x0000000041414800 nid=0x2f95 runnable 

"GC task thread#1 (ParallelGC)" prio=10 tid=0x00007f512c001000 nid=0x2f96 runnable 

"GC task thread#2 (ParallelGC)" prio=10 tid=0x00007f512c002800 nid=0x2f97 runnable 

"GC task thread#3 (ParallelGC)" prio=10 tid=0x00007f512c004800 nid=0x2f98 runnable 

"GC task thread#4 (ParallelGC)" prio=10 tid=0x00007f512c006800 nid=0x2f99 runnable 

"GC task thread#5 (ParallelGC)" prio=10 tid=0x00007f512c008000 nid=0x2f9a runnable 

"GC task thread#6 (ParallelGC)" prio=10 tid=0x00007f512c00a000 nid=0x2f9b runnable 

"GC task thread#7 (ParallelGC)" prio=10 tid=0x00007f512c00c000 nid=0x2f9c runnable 

"VM Periodic Task Thread" prio=10 tid=0x00007f512c089000 nid=0x2fa4 waiting on condition 

Claramente, la mayor parte de los hilos tienen que ver con el manejo de memoria: Hay 8 hilos recolector de basura, además del detector de memoria baja. Finalizer y Reference Handler suenan como si también estuvieran involucrados en la administración de la memoria.

C2 CompilerThread0/1 casi seguro tienen que ver con la compilación justo a tiempo.

VM Periodic Task Thread se explica aquí: What is the "VM Periodic Task Thread"?

En cuanto al propósito exacto de los hilos restantes, no estoy seguro.

+0

Bien, supongo que esto explica mucho. Pero, ¿cómo obtuviste esta producción? – jlh

+0

El subproceso de finalizador es el que ejecuta el código de finalización de objetos recogidos de basura en segundo plano. Ahora estoy realmente intrigado de lo que hace el hilo del controlador de referencia: veamos si encontramos algo al respecto;) – Voo

+0

@jlh: utilicé 'jstack'. – NPE

4

Hice esta captura de pantalla usando jvisualvm. hilos de ejecución (en Eclipse):

Java Threads

ejecutan el mismo programa que el archivo * .jar; solo hay 4 hilos daemon y 1 hilo en ejecución.

+0

La ejecución de un archivo .jar no hizo ninguna diferencia para mí. Tu salida parece que la ejecutas en modo de depuración, ¿es correcto? ¿Cómo produjo su archivo .jar? – jlh

+0

A exportó el programa como archivo ejecutable * .jar en eclipse y lo ejecutó a través de la línea de comando con 'java -jar file.jar'. La captura de pantalla consistía en ejecutarlo en eclipse con 'Ejecutar como> Aplicación Java '. – MasterCassim

3

Esto puede no responder a la pregunta, pero al menos ayuda a entender lo que está pasando. Para obtener una muestra precisa de los hilos, obtenga el formulario de la lista dentro de su aplicación. (En lugar de partir de las herramientas de depuración.)

JVM w/o Instrumentación

  • Tema: principal
  • Tema: Referencia Handler
  • Tema: Señal Dispatcher
  • Tema: Adjuntar Oyente
  • Hilo: Finalizador

JVM w/Instrumentación (jconsole)

  • Tema: principal
  • Tema: conexión de servidor JMX tiempo de espera de 12
  • Tema: RMI TCP de conexión (1) -10.1.100.40
  • Subproceso: RMI TCP Connection (2) -10.1.100.40
  • Tema: Finalizer
  • Tema: Referencia Handler
  • Tema: RMI Programador (0)
  • Tema: Señal Dispatcher
  • Tema: RMI TCP Accept-0
  • Tema: Adjuntar Listener

Experimento

  1. ejecute el siguiente código
  2. jconsole lanzamiento y conectar a la JVM
public class JVM { 
    public static void main(String... args) throws InterruptedException { 
    for (java.util.Enumeration<?> e = System.getProperties().propertyNames(); e.hasMoreElements();) { 
     String prp = (String) e.nextElement(); 
     if (prp.startsWith("java.vm") || prp.startsWith("os.")) { 
     System.out.format("[%s]=%s%n", prp, System.getProperty(prp)); 
     } 
    } 
    java.text.DateFormat df = new java.text.SimpleDateFormat("HH:mm:ss.SSS"); 
    for(;;) { 
     System.out.format("%s Sampling current threads...%n", df.format(new java.util.Date())); 
     java.util.Map<Thread, StackTraceElement[]> stacks = Thread.getAllStackTraces(); 
     System.out.format("> Thread Count: %d%n", stacks.size()); 
     for (java.util.Map.Entry<Thread, StackTraceElement[]> entry : stacks.entrySet()) { 
     Thread thread = entry.getKey(); 
     StackTraceElement[] stack = entry.getValue(); 
     System.out.format("> Thread: %s%n", thread.getName()); 
     // Throwable t = new Throwable("Thread: " + thread.getName()); 
     // t.setStackTrace(stack); 
     // t.printStackTrace(System.out); 
     } 
     java.util.concurrent.TimeUnit.SECONDS.sleep(10); 
    } 
    } 
} 

salida

[java.vm.version]=16.2-b04 
[java.vm.vendor]=Sun Microsystems Inc. 
[java.vm.name]=Java HotSpot(TM) Client VM 
[java.vm.specification.name]=Java Virtual Machine Specification 
[os.arch]=x86 
[java.vm.specification.vendor]=Sun Microsystems Inc. 
[os.name]=Windows XP 
[os.version]=5.1 
[java.vm.specification.version]=1.0 
[java.vm.info]=mixed mode, sharing 
14:03:49.199 Sampling current threads... 
> Thread Count: 5 
> Thread: main 
> Thread: Reference Handler 
> Thread: Signal Dispatcher 
> Thread: Attach Listener 
> Thread: Finalizer 
14:03:59.200 Sampling current threads... 
> Thread Count: 10 
> Thread: main 
> Thread: JMX server connection timeout 12 
> Thread: RMI TCP Connection(1)-10.1.100.40 
> Thread: RMI TCP Connection(2)-10.1.100.40 
> Thread: Finalizer 
> Thread: Reference Handler 
> Thread: RMI Scheduler(0) 
> Thread: Signal Dispatcher 
> Thread: RMI TCP Accept-0 
> Thread: Attach Listener 
0

Cuando se suele ejecutar un programa Java, se ejecuta en una máquina virtual. Algunos de los hilos que ve son para la máquina virtual, ya sea para el funcionamiento de la máquina virtual o para aumentar la eficiencia (los hilos del compilador) cuando se encuentra un candidato potencial para la optimización (llamado "punto caliente"), estos hilos compilarlo desde el código de Java Byte al código de máquina para la plataforma en la que se está ejecutando la JVM).

La mayoría de los otros hilos son para la gestión de la memoria. Hay tantos para ofrecer una mejor experiencia de usuario (la interfaz de usuario/interfaz se bloqueará por un tiempo menor si la recolección de basura finaliza más rápido).

Cuestiones relacionadas