并发编程(一)java运行总共有几条线程?

(一)java启动后拥有的线程

我们首先看代码,打印普通main方法执行时,程序到底有几条线程,线程又是怎样的。

public class ThreadPrint {
    public static void main(String[] args) throws JsonProcessingException, InterruptedException {
        // 获取Java线程管理MXBean
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        // 不需要获取同步的monitor和synchronizer信息,仅获取线程和线程堆栈信息
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
        // 遍历线程信息,仅打印线程ID和线程名称信息
        for (ThreadInfo threadInfo : threadInfos) {
            System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.
                    getThreadName());
        }
        Thread.sleep(1000000);
    }
}

输出结果如下:

 

下面分别介绍一下正在运行的线程:

  • [6] Monitor Ctrl-Break

      跟JVM 关系不大,他是 IDEA 通过反射的方式,开启一个随着我们运行的jvm进程开启与关闭的一个监听线程。
    复制代码
  • [5] Attach Listener

      附加侦听器,简单来说,他是 jdk 里边一个工具类提供的jvm进程之间通信的工具。
      举例来说,比如在cmd中输入 java -version,jvm中jstat、jstack、jmap、dump等。
    复制代码

    如果自己电脑没有打印这一行,可以尝试开启我们这个线程的两个方式:

    1. 通过 vm,参数开启。-XX: StartAttachListener
    2. 2.延迟开启: md --java -version --> JVM 实时开启Attach Listener线程
  • [4] Signal Dispatcher

      信号分发器。我们通过 cmd 发送jstack,传到了 jvm 进程,这时候信号分发器就要发挥作用了。
    复制代码
  • [3] Finalizer

      JVM 垃圾回收相关的内容。此处只做简单的介绍。 
      1. 只有当开始一轮垃圾收集的时候,才会开始调用finalize方法。 
      2. daemon prio=10 高优先级的守护线程。   
      3. jvm在垃圾收集的时候,会将失去引用的对象封装到我们的 Fianlizer 对象(Reference), 放入我们的 F-queue 队列中。由 Finalizer 线程执行inalize方法
    复制代码
  • [2] Reference Handler

      引用处理的线程。强,软,弱,虚。 -GC 有不同表现 - JVM深入分析
    复制代码
  • [1] main

      就是我们运行的main线程
    复制代码

(二)查看线程级别

1.可以在idea工具Terminal中输入jps查看进程的pid,我们可以看到ThreadPrint的pid是37720

2.再通过jstack pid命令可以查看到进程日志

 

 ​​​​​​​

 

其中我们把需要了解的部分拿出来 daemon表示守护线程 prio表示jvm中的优先级 os_prio表示线程在操作系统中所占的优先级

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x0000000018e04800 nid=0xc918 runnable [0x000000001967f000]
Monitor Ctrl-Break是在idea中特有的线程

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x00000000171eb000 nid=0x9230 waiting on condition [0x0000000000000000]
    prio=5 延迟开启的问题

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x00000000171d3800 nid=0x9054 runnable [0x0000000000000000]


"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x00000000171c6800 nid=0xc26c in Object.wait() [0x0000000018b1e000]
(Finalizer 专注垃圾收集,垃圾收集 -- 并行收集,不阻碍用户线程,低优先级线程。 prio=8 他是一个守护线程啊。而且这个线程目前并没有真正的开启,不足以发生minorgc或者是 full gc)


"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x000000001575f000 nid=0x9a38 in Object.wait() [0x0000000018a1f000]
(引用处理线程-GC相关线程:GC 很重要,优先级高)


"main" #1 prio=5 os_prio=0 tid=0x0000000003624000 nid=0xaba0 waiting on condition [0x000000000351f000]
(操作系统面向的是JVM 进程,JVM 进程里面向的是 我们的main函数,。所以对于我们的操作系统如何看待我们的main函数优先级,都无关紧要。 只要os 给我们jvm进程足够公平的优先级就行。)
复制代码

(三)总结

在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。处理器在这些线程上高速切换,让使用者感觉到这些线程在同时执行。

当前的main函数就是一个 JVM 进程。 打印出来的6条线程信息就是进程中的多条线程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值