`
java-boy
  • 浏览: 248372 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java 内部工作线程介绍

    博客分类:
  • Java
阅读更多

Java程序运行的过程中,不但包括开发者启动的主线程和子线程。还包括很多内部线程。了解这些线程,对了解Java工作原理,及复杂环境下debug会有帮助。

 

首先需要查看Java程序的内部线程,我使用以下两种方法查看Java下的线程:

        1.Jconsole——JDK自带的JMX查看管理工具(GUI)。

        2.Linux下使用kill -3 processId ,发送命令3号信号——QUIT。可以得到该进程的线程堆栈及内存占用情况输出。

        3.jstack <pid>——JDK自带的查看堆栈工具。

 

两种方法对比:

       平常写程序用jconsole,是很好的工具。因为Jconsole可以实时查看内存和堆栈情况,而kill则不能。但对于生产情况kill还是有用武之地的。

       但这回, Kill方法输出的比Jconsole要更全,Jconsole使用的是JMX主要用来是查看进程工作情况,会隐藏一些内部的线程。对写程序没什么影响,但这次我们希望得到全部内部线程用来分析,所以Jconsole是不够用的。

 

需要先说明一下,我的这次测试,是在SUN  HotSpot(TM) Client VM (14.0-b16)——JDK6 情况下的线程结果,由于JVM可以根据协议各自厂商自己实现,可能会有出入。

 

好了,我们先看看跑一个HelloWorld需要开启几个线程:
我的kill -3 processID 后的结果是:

 

Full thread dump Java HotSpot(TM) Client VM (14.0-b16 mixed mode, sharing):

"Low Memory Detector" daemon prio=10 tid=0x08096400 nid=0x6e5 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"CompilerThread0" daemon prio=10 tid=0x08093400 nid=0x6e4 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x08091800 nid=0x6e3 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=10 tid=0x08080400 nid=0x6e2 in Object.wait() [0xb52b2000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x8b7d0b00> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
        - locked <0x8b7d0b00> (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=0x0807ec00 nid=0x6e1 in Object.wait() [0xb5303000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x8b7d0a08> (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 <0x8b7d0a08> (a java.lang.ref.Reference$Lock)

"main" prio=10 tid=0x08059000 nid=0x6df waiting on condition [0xb7577000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.test.HelloWorld.main(HelloWorld.java:12)

"VM Thread" prio=10 tid=0x0807d000 nid=0x6e0 runnable

"VM Periodic Task Thread" prio=10 tid=0x080aa000 nid=0x6e6 waiting on condition

JNI global references: 597

Heap
 def new generation   total 960K, used 200K [0x8b7d0000, 0x8b8d0000, 0x8bcb0000)
  eden space 896K,  22% used [0x8b7d0000, 0x8b802068, 0x8b8b0000)
  from space 64K,   0% used [0x8b8b0000, 0x8b8b0000, 0x8b8c0000)
  to   space 64K,   0% used [0x8b8c0000, 0x8b8c0000, 0x8b8d0000)
 tenured generation   total 4096K, used 0K [0x8bcb0000, 0x8c0b0000, 0x8f7d0000)
   the space 4096K,   0% used [0x8bcb0000, 0x8bcb0000, 0x8bcb0200, 0x8c0b0000)
 compacting perm gen  total 12288K, used 18K [0x8f7d0000, 0x903d0000, 0x937d0000)
   the space 12288K,   0% used [0x8f7d0000, 0x8f7d4a30, 0x8f7d4c00, 0x903d0000)
    ro space 8192K,  74% used [0x937d0000, 0x93dc9cc8, 0x93dc9e00, 0x93fd0000)
    rw space 12288K,  59% used [0x93fd0000, 0x946e7540, 0x946e7600, 0x94bd0000)

 

 

为了大家能看清,我特意全拷了上来。需要特意说明的是,我使用的是Sleep方法将进程停住,而不是我通常使用的‘调试’方法。为什么已后进行详细说明。

 

我们能看见HelloWorld实际上创建了如下线程:

"Low Memory Detector"
"CompilerThread0"
"Signal Dispatcher"
"Finalizer"
"Reference Handler"
"main"
"VM Thread"
"VM Periodic Task Thread"

 

由于我手头上的资料也不是很全,简单说明一下都是干什么用的。

"Low Memory Detector" 负责对可使用内存进行检测,如果发现可用内存低,分配新的内存空间。

"CompilerThread0" 用来调用JITing,实时编译装卸class。

"Signal Dispatcher" 负责分发内部事件。

"Finalizer" 负责调用Finalizer方法。

"Reference Handler" 负责处理引用。

"main" 是主线程。

"VM Thread", "VM Periodic Task Thread"从名字上看是虚机内部线程。(这两个在Jconsole下看不见)

 

我们还可以看出实际上只有"main","VM Thread","Low Memory Detector" 在工作。

而"Low Memory Detector" ,"CompilerThread0","Signal Dispatcher","Finalizer","Reference Handler"都是daemo进程。

 

之后我用Jconsole查看了一下,发现多了几个线程:

 

"RMI TCP Connection(4)-127.0.1.1" daemon prio=10 tid=0x08201000 nid=0x2846 runnable [0xac968000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:129)
	at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
	at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
	- locked <0xad7543a8> (a java.io.BufferedInputStream)
	at java.io.FilterInputStream.read(FilterInputStream.java:66)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:517)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)

"RMI TCP Connection(3)-127.0.1.1" daemon prio=10 tid=0x081edc00 nid=0x2845 runnable [0xac9b9000]
   java.lang.Thread.State: RUNNABLE
	at java.net.SocketInputStream.socketRead0(Native Method)
	at java.net.SocketInputStream.read(SocketInputStream.java:129)
	at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
	at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
	- locked <0xad7565c0> (a java.io.BufferedInputStream)
	at java.io.FilterInputStream.read(FilterInputStream.java:66)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:517)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)

"RMI TCP Connection(idle)" daemon prio=10 tid=0x081e7000 nid=0x2841 waiting on condition [0xaca0a000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0xad706d50> (a java.util.concurrent.SynchronousQueue$TransferStack)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
	at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:424)
	at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:323)
	at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:874)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:945)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
	at java.lang.Thread.run(Thread.java:619)

"JMX server connection timeout 15" daemon prio=10 tid=0x081d6800 nid=0x2839 in Object.wait() [0xaca5b000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0xad7136e8> (a [I)
	at com.sun.jmx.remote.internal.ServerCommunicatorAdmin$Timeout.run(ServerCommunicatorAdmin.java:150)
	- locked <0xad7136e8> (a [I)
	at java.lang.Thread.run(Thread.java:619)

"RMI Scheduler(0)" daemon prio=10 tid=0x08160c00 nid=0x2838 waiting on condition [0xacaac000]
   java.lang.Thread.State: TIMED_WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0xad6fdf18> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:198)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:1963)
	at java.util.concurrent.DelayQueue.take(DelayQueue.java:164)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:583)
	at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:576)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
	at java.lang.Thread.run(Thread.java:619)

"RMI TCP Connection(1)-127.0.1.1" daemon prio=10 tid=0x080fc800 nid=0x2837 in Object.wait() [0xacafd000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
	at java.lang.Object.wait(Native Method)
	- waiting on <0xad740780> (a com.sun.jmx.remote.internal.ArrayNotificationBuffer)
	at com.sun.jmx.remote.internal.ArrayNotificationBuffer.fetchNotifications(ArrayNotificationBuffer.java:417)
	- locked <0xad740780> (a com.sun.jmx.remote.internal.ArrayNotificationBuffer)
	at com.sun.jmx.remote.internal.ArrayNotificationBuffer$ShareBuffer.fetchNotifications(ArrayNotificationBuffer.java:209)
	at com.sun.jmx.remote.internal.ServerNotifForwarder.fetchNotifs(ServerNotifForwarder.java:258)
	at javax.management.remote.rmi.RMIConnectionImpl$2.run(RMIConnectionImpl.java:1227)
	at javax.management.remote.rmi.RMIConnectionImpl$2.run(RMIConnectionImpl.java:1225)
	at javax.management.remote.rmi.RMIConnectionImpl.fetchNotifications(RMIConnectionImpl.java:1231)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:305)
	at sun.rmi.transport.Transport$1.run(Transport.java:159)
	at java.security.AccessController.doPrivileged(Native Method)
	at sun.rmi.transport.Transport.serviceCall(Transport.java:155)
	at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:535)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:790)
	at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:649)
	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
	at java.lang.Thread.run(Thread.java:619)

"RMI TCP Accept-0" daemon prio=10 tid=0x08107400 nid=0x2835 runnable [0xacb4e000]
   java.lang.Thread.State: RUNNABLE
	at java.net.PlainSocketImpl.socketAccept(Native Method)
	at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:390)
	- locked <0xad6fe0e8> (a java.net.SocksSocketImpl)
	at java.net.ServerSocket.implAccept(ServerSocket.java:453)
	at java.net.ServerSocket.accept(ServerSocket.java:421)
	at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:34)
	at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:369)
	at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:341)
	at java.lang.Thread.run(Thread.java:619)

"Attach Listener" daemon prio=10 tid=0x080fb000 nid=0x2834 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE
 

我们从名字可以看出来RMI开头的5个是管理RMI的线程。

JMX的是管理JMX线程。

"Attach Listener"现在不明,但也应该跟Jconsole有关。

以上全部是daemon线程。

 

主要都是用来Jconsole管理该进程时使用的。

 

之后,我又尝试用‘断点’,debug模式,停下程序,发现又多出了三个线程(在jconsole下一样看不见)。

"JDWP Command Reader" daemon prio=10 tid=0x080cb400 nid=0x2827 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"JDWP Event Helper Thread" daemon prio=10 tid=0x080c9400 nid=0x2826 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

"JDWP Transport Listener: dt_socket" daemon prio=10 tid=0x080c6c00 nid=0x2823 runnable [0x00000000]
   java.lang.Thread.State: RUNNABLE

 

 JDWP是Java Debug Wire Protocol的缩写,是Java Debug使用的一种协议。以上三个线程,应该就是用来Debug时,创建的。以上三个全是daemon线程。

 

由于资料缺少,就先写到这里了,已后有资料了在补...........

 

 

 

参考资料:

http://en.allexperts.com/q/Java-1046/Jvm-threads.htm

http://java.sun.com/j2se/1.5.0/docs/guide/jpda/jdwp-spec.html

6
0
分享到:
评论
5 楼 eagledame 2015-08-20  
grefr 写道
关于JVM内部运行线程的介绍,可以看看这个文章,写的相当不错
http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp47



这个资料好
4 楼 kuangxiao163 2014-03-07  
jactive 写道
不错  至少知道了 jconsole ,谢谢

不过我在 fc 下 kill -3 没有任何输出...  应该怎么做呢?


是在java运行的控制台下的输出。
3 楼 GuolinLee 2012-02-07  
长见识了,我第一次用Jconsole来看到有那么隐藏的线程的时候吃了一惊,没想到还有这么多隐藏的线程啊
2 楼 java-boy 2009-11-18  
jstack <pid> 也可以查看进程运行情况。
1 楼 jactive 2009-11-17  
不错  至少知道了 jconsole ,谢谢

不过我在 fc 下 kill -3 没有任何输出...  应该怎么做呢?

相关推荐

    java多线程的讲解和实战

    8. **并发集合类**:Java提供了并发安全的集合类,如`ConcurrentHashMap`, `CopyOnWriteArrayList`, `BlockingQueue`等,它们内部实现了线程安全的算法,可以在多线程环境下高效使用。 9. **线程中断**:`interrupt...

    java10个线程按照顺序打印1-100

    这样,我们可以在每个线程内部设置条件变量,使得每个线程打印一个数字后,通知下一个线程开始执行。 2. **wait(), notify() 和 notifyAll()**:这些方法位于`Object`类中,用于线程间的通信。在线程A中调用`wait()...

    Java多线程编程核心技术_完整版_java_

    1. Thread.interrupt():用于中断线程,但不一定立即停止,需要在run()方法内部检查中断标志并作出相应处理。 2. InterruptedException:线程被中断时抛出的异常,通常需要捕获并处理。 九、线程死锁 1. 死锁的概念...

    Java多线程练习题

    Java提供了一系列并发容器,如ConcurrentHashMap、CopyOnWriteArrayList等,它们内部实现了线程安全,能够在多线程环境下高效地使用。 八、死锁 当两个或更多线程互相等待对方释放资源而无法继续执行时,就会发生...

    JAVA多线程编程技术PDF

    在Java编程领域,多线程是一项至关重要的技术,它允许程序同时执行多个任务,从而提高系统资源的利用率和程序的响应速度。这份“JAVA多线程编程技术PDF”是学习和掌握这一领域的经典资料,涵盖了多线程的全部知识点...

    JAVA教程解析Java的多线程机制

    而Java语言定义的线程同样包括一个内存入口点地址、一个出口点地址以及能够顺序执行的代码序列,但是线程不能独立于进程之外执行,它必须运行在一个活跃的进程内部,因此线程可以被视为程序内部具有并发性的顺序代码...

    java 查看JVM中所有的线程的活动状况

    在Java编程环境中,了解JVM(Java虚拟机)中所有线程的活动状态对于调试多线程程序至关重要。本文将详细讲解如何查看JVM中的线程活动情况,并提供相关示例代码。 首先,Java提供了`java.lang.management....

    java实现多线程下载

    - **下载逻辑**:每个线程内部需要实现下载逻辑,可能涉及到HTTP请求,使用`java.net.URL`, `java.net.URLConnection`等类进行网络通信,获取文件数据。 - **同步控制**:为了防止多个线程同时写入同一个文件导致...

    java多线程机制 详解

    Java的多线程机制是Java语言的一大特性,它允许程序同时执行多个任务,提升程序响应速度,优化资源利用率。在Java中,线程是程序执行的最小单位,一个进程可以包含多个线程,每个线程都有自己独立的生命周期,包括...

    Java多线程文档

    Java提供了线程安全的集合类,如Vector、ConcurrentHashMap、CopyOnWriteArrayList等,它们在内部实现了同步机制,可以安全地在多线程环境下使用。 六、死锁、活锁与饥饿 1. 死锁:两个或多个线程相互等待对方释放...

    Java多线程下载器

    这可以通过在每个线程内部更新全局计数器,或者使用共享的数据结构(如BlockingQueue)来实现。另外,还可以使用Java的Swing或JavaFX库构建图形用户界面,实时展示下载进度。 6. **错误处理**:在多线程环境中,...

    Java线程.ppt

    首先,线程是一个程序内部的顺序控制流,它是执行程序的最小单位。线程与进程的主要区别在于,进程拥有独立的内存空间和系统资源,而线程则是轻量级的进程,它们共享同一块内存空间和系统资源,因此线程间的切换成本...

    java多线程之赛马程序实验8多线程练习下载进度

    在Java编程中,多线程是一项关键特性,它允许程序同时执行多个任务,极大地提高了效率。本实验"java多线程之赛马程序实验8多线程练习下载进度"聚焦于如何利用多线程来模拟实际场景中的下载进度显示。在这一过程中,...

    Java编写线程动画

    2. 线程:线程是进程内部的一个执行流,它共享进程的内存空间和资源,但拥有独立的程序计数器、栈和局部变量。同一进程内的线程可以高效地共享数据,减少了上下文切换的成本。 在Java中,我们可以使用以下方法创建...

    java多线程.pdf

    ### Java多线程知识点详解 #### 一、Java多线程概述 **Java多线程**是指在Java程序中能够同时执行多个线程的技术。这种技术使得程序可以在多个任务之间并发执行,从而提高了程序的效率和资源利用率。本文将根据...

    Java多线程的总结

    Java集合框架中有一些线程安全的类,如Vector、HashTable、ConcurrentHashMap等,它们内部实现了同步机制,可以在多线程环境中直接使用,避免了手动同步的复杂性。 十、线程局部变量 ThreadLocal为每个线程都创建了...

    java中线程的应用例子

    线程内部需要检查这个标志并适当地响应中断请求。 总的来说,理解和掌握Java中的线程应用是成为熟练Java开发者的关键一步。通过合理地使用线程,可以优化程序性能,提高用户体验。在实际项目中,务必关注线程安全和...

    java线程深入解析

    线程允许一个程序内部同时执行多个独立的控制流,使得程序能够更高效地利用处理器资源。本文将深入解析Java线程的相关知识点,包括线程的定义、创建、状态管理、线程同步和安全问题。 1. **线程定义** 在Java中,...

    java多线程设计

    4. 使用并发集合:Java并发包(java.util.concurrent)提供了线程安全的集合,如ConcurrentHashMap、CopyOnWriteArrayList等,它们内部实现了线程同步,无需额外的同步控制。 5. 原子操作(Atomic):AtomicInteger...

Global site tag (gtag.js) - Google Analytics