简单的Java示例运行14个线程。 为什么?

以下简单的Java代码:

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

运行使用14个线程。 我知道有些GC线程在后台运行,但其他的是什么? 为什么有那么multithreading? 我在Java 1.6.0_26上使用Gentoo Linux。 使用Eclipse的编译器或javac进行编译并没有什么区别(在Eclipse中以调试模式运行它会增加3个线程,但这可能是合理的)。

我的JVM(1.6.0_26)默认生成更multithreading。 大多数都有相当具有描述性的名称暗示其目的:

 "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 

显然,大多数线程都与内存处理有关:有8个垃圾收集器线程,还有低内存检测器。 FinalizerReference Handler听起来像是他们也参与了内存管理。

C2 CompilerThread0/1几乎肯定与即时编译有关。

VM Periodic Task Thread在这里解释: 什么是“VM Periodic Task Thread”?

至于其余线程的确切目的,我不确定。

我使用jvisualvm制作了这个截图。 运行线程(在eclipse中):

Java线程

运行与* .jar文件相同的程序; 只有4个守护程序线程和1个活动线程运行。

这可能无法解决问题,但至少有助于了解正在发生的事情。 要获得准确的线程示例,请在应用程序中获取列表表单。 (而不是从调试工具。)

JVM没有仪表

  • 线程:主要
  • 线程:参考处理程序
  • 线程:信号调度程序
  • 线程:附加监听器
  • 线程:终结器

JVM w / Instrumentation(jconsole)

  • 线程:主要
  • 线程:JMX服务器连接超时12
  • 线程:RMI TCP连接(1)-10.1.100.40
  • 线程:RMI TCP连接(2)-10.1.100.40
  • 线程:终结器
  • 线程:参考处理程序
  • 线程:RMI调度程序(0)
  • 线程:信号调度程序
  • 线程:RMI TCP Accept-0
  • 线程:附加监听器

实验

  1. 执行以下代码
  2. 启动jconsole并连接到该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 stacks = Thread.getAllStackTraces(); System.out.format("> Thread Count: %d%n", stacks.size()); for (java.util.Map.Entry 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); } } } 

产量

 [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 

通常运行Java程序时,它在虚拟机上运行。 您看到的一些线程是针对VM的 – 无论是为了VM的运行还是为了提高效率(编译器线程 – 当找到潜在的优化候选者时(称为“热点”),这些线程将将它从Java Byte代码编译为运行JVM的平台的机器代码。

大多数其他线程用于内存管理。 有很多可以提供更好的用户体验(如果垃圾收集完成得更快,UI /接口将挂起更短的时间)。