2011-10-08 38 views
12

以下瑣碎Java代碼:使用14個螺紋簡單的Java示例運行14個線程。爲什麼?

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

上運行。我知道一些GC線程在後臺運行,但其他人爲什麼?爲什麼有這麼多的線程?我在Gentoo Linux上使用Java 1.6.0_26。使用Eclipse的編譯器或javac編譯並沒有什麼不同(在調試模式下在Eclipse中運行它會爲它增加3個線程,但這可能是合理的)。

+1

你是如何運行你的代碼?如果您是從IDE內運行它的,那麼您的IDE本身是否可以用Java編寫(並運行)? – DevSolar

+3

我很好奇 - 你如何確定它運行14個線程? – Coffee

+0

是什麼讓你覺得有14個線程? –

回答

14

默認情況下,我的JVM(1.6.0_26)會產生更多的線程。最有暗示他們的目的很描述性的名字:

"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在此說明:What is the "VM Periodic Task Thread"?

至於其餘線程的確切目的,我不知道。

+0

不錯,我想這解釋了很多。但你是如何得到這個輸出的? – jlh

+0

終結器線程是在後臺運行垃圾收集對象的終結代碼的線程。現在我對引用處理程序線程正在做的事情非常感興趣 - 讓我們看看我們是否能找到相關的東西;) – Voo

+0

@jlh:我使用了'jstack'。 – NPE

4

我使用jvisualvm製作此屏幕截圖。正在運行的線程(在eclipse):

Java Threads

運行同一程序作爲* .jar文件;只有4個守護進程線程和1個活動線程正在運行。

+0

運行.jar文件對我沒有任何影響。你的輸出看起來像你在調試模式下運行它,這是否正確?你是如何生成你的.jar文件的? – jlh

+0

在eclipse中將程序導出爲可執行的* .jar文件,並通過命令行使用'java -jar file.jar'執行它。屏幕截圖是運行在eclipse中的Run as> Java Application'。 – MasterCassim

3

這可能不會回答這個問題,但至少有助於理解發生了什麼。要獲得線程的準確示例,請在您的應用程序中獲取列表表單。 (而不是從調試工具。)

JVM W/O儀器

  • 主題:主要
  • 主題:指向處理器
  • 主題:信號調度
  • 主題:附上聽衆
  • 主題:終結者

JVM瓦特/儀器(JConsole的)

  • 螺紋:主
  • 螺紋:JMX服務器連接超時12
  • 螺紋:RMI TCP連接(1)-10.1.100.40
  • 主題:RMI TCP連接(2)-10.1.100。40
  • 螺紋:終結
  • 螺紋:參考處理程序
  • 螺紋:RMI調度器(0)
  • 線程:信號分派器
  • 螺紋:RMI TCP接受-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<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); 
    } 
    } 
} 

輸出

[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

當你通常運行Java程序,它運行在一臺虛擬機。您看到的一些線程是針對虛擬機的 - 既可以用於虛擬機的運行,也可以提高效率(編譯器線程 - 當發現潛在的優化候選者(稱爲「熱點」)時,這些線程將將其從Java Byte代碼編譯爲運行JVM的平臺的機器代碼)。

大多數其他線程用於內存管理。有很多提供更好的用戶體驗(如果垃圾收集更快完成,UI /界面將掛起時間較短)。

相關問題