2011-10-08 8 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を実行している場合は、IDE自体がJavaで記述されていて実行中である可能性がありますか? – DevSolar

+3

私は興味があります - あなたは14スレッドを実行することをどのように決定していますか? – Coffee

+0

あなたは14のスレッドがあると思いますか? –

答えて

14

My 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を使用してこのスクリーンショットを作成しました。 (日食で)実行中のスレッド:

Java Threads

* .jarファイルと同じプログラムを実行します。デーモンスレッドは4つしかなく、実行スレッドは1つしかありません。

+0

.jarファイルを実行しても私にとっては何の違いもありませんでした。あなたの出力はデバッグモードで実行されているようですが、それは正しいですか?どうやって.jarファイルを作りましたか? – jlh

+0

Aはeclipseで実行可能な* .jarファイルとしてプログラムをエクスポートし、 'java -jar file.jar'でコマンドラインで実行しました。 Screenshotは 'Run as> Java Application'を使ってeclipseで実行したものです。 – MasterCassim

3

これは質問に答えないかもしれませんが、少なくとも何が起こっているかを理解するのに役立ちます。スレッドの正確なサンプルを取得するには、アプリケーション内のリストフォームを取得します。 (代わりのデバッグツールから。)

JVM W /計装O

  • スレッド:メイン
  • スレッド:リファレンスハンドラ
  • スレッド:シグナルディスパッチャ
  • スレッド:アタッチ・リスナー
  • スレッド:ファイナライザー

JVM /計装(jconsoleを)

  • スレッドW:主
  • スレッド:JMXサーバ接続タイムアウト12
  • スレッド:RMI TCPコネクション(1)-10.1.100.40
  • スレッド:RMI TCP接続(2)-10.1.100。40
  • スレッド:ファイナライザ
  • スレッド:リファレンスハンドラ
  • スレッド:RMIは、スケジューラ(0)
  • スレッド:信号Dispatcherは
  • スレッド:RMI TCPのAccept-0
  • スレッド:アタッチリスナー

実験

  1. 次のコード
  2. 起動jconsoleを実行して、通常のJavaプログラムを実行すると、それが実行される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

を接続仮想マシン。表示されるスレッドの一部は、VMの機能(VMの機能または効率の向上)(コンパイラスレッド - 潜在的な最適化候補が見つかった場合(「ホットスポット」と呼ばれる)、これらのスレッドはJava Byteコードから、JVMが実行されているプラ​​ットフォームのマシンコードにコンパイルします)。

他のほとんどのスレッドはメモリ管理用です。より良いユーザーエクスペリエンスを提供するためには非常に多くのものがあります(ガーベジコレクションがより速く終了すると、UI /インターフェイスが短時間停止します)。

関連する問題