java线程运行无限次_java程序运行时到底有多少个活跃线程

先贴上最原始的代码,疑惑的开始。

public class Solution {

public static void main(String[] args) {

T t1 = new T();

T t2 = new T();

t1.start();

System.out.println(Thread.activeCount());

t2.start();

}

static class T extends Thread{

@Override

public void run() {

try {

Thread.sleep(1000);

}catch (InterruptedException e){

e.printStackTrace();

}

}

}

}

上面的程序应该输出数字2?还是3?本着严谨的态度在ide上面跑了一下,本来以为是2,结果是3. t2的运行不是在打印之前嘛?为什么会是3呢?难道说t2也算进去了?继续去测试一下。

public static void main(String[] args) {

T t1 = new T();

T t2 = new T();

t1.start();

System.out.println(Thread.activeCount());

t2.start();

System.out.println(Thread.activeCount());

}

结果是3 4.这就说明另外一个活跃的线程不是它t2,另外有一个线程。顺着这个思路,去看看到底哪些线程在运行。

public static void main(String[] args) {

T t1 = new T();

T t2 = new T();

t1.start();

System.out.println(Thread.activeCount());

Map maps = Thread.getAllStackTraces();

for ( Thread thread:maps.keySet()){

System.out.println(thread.getName());

}

t2.start();

System.out.println(Thread.activeCount());

}

把所有的线程都打印出来看看。下面是运行结果。

f37579234b8f

1.png

运行结果让人大吃一惊,这是什么啊,不算t2都有7个活跃的进程,为什么Thread.activeCount()只有3或者4个呢?这是什么鬼哦。为了搞清楚到底是怎么回事,就去看看Thread.activeCount()的源码吧。下面展示的就是源码部分。

/**

* Returns an estimate of the number of active threads in the current

* thread's {@linkplain java.lang.ThreadGroup thread group} and its

* subgroups. Recursively iterates over all subgroups in the current

* thread's thread group.

*

*

The value returned is only an estimate because the number of

* threads may change dynamically while this method traverses internal

* data structures, and might be affected by the presence of certain

* system threads. This method is intended primarily for debugging

* and monitoring purposes.

*

* @return an estimate of the number of active threads in the current

* thread's thread group and in any other thread group that

* has the current thread's thread group as an ancestor

*/

public static int activeCount() {

return currentThread().getThreadGroup().activeCount();

}

看了源码,我们了解到原来Thread.activeCount()只是计算当前线程的线程组里面有多少活跃线程,而不是所有的活跃线程,这也就解释了,为什么会出现数目对不上的情况。接下来,我们看看每个线程组都是哪些线程。

public static void main(String[] args) {

T t1 = new T();

T t2 = new T();

t1.start();

System.out.println("当前活跃线程数量:"+Thread.activeCount());

ThreadGroup group = Thread.currentThread().getThreadGroup();

System.out.println("当前线程组的名称:"+group.getName());

Thread[] list1 = new Thread[group.activeCount()];

group.enumerate(list1);

for (Thread thread:list1){

System.out.println(thread.getName());

}

ThreadGroup groupParent = group.getParent();

System.out.println("当前线程组的名称:"+groupParent.getName());

Thread[] list2 = new Thread[groupParent.activeCount()];

groupParent.enumerate(list2);

for (Thread thread:list2){

System.out.println(thread.getName());

}

}

上面程序的运行结果如下图所示。

f37579234b8f

2.png

这次基本就清清楚楚,明明白白了。其中Thread-0就是我们的t1线程。接下来简单的描述一下其他的线程都是干什么的。参考http://ifeve.com/jvm-thread/

Attach Listener

Attach Listener线程是负责接收到外部的命令,而对该命令进行执行的并且吧结果返回给发送者。通常我们会用一些命令去要求jvm给我们一些反 馈信息,如:java -version、jmap、jstack等等。如果该线程在jvm启动的时候没有初始化,那么,则会在用户第一次执行jvm命令时,得到启动。

Signal Dispatcher

前面我们提到第一个Attach Listener线程的职责是接收外部jvm命令,当命令接收成功后,会交给signal dispather线程去进行分发到各个不同的模块处理命令,并且返回处理结果。signal dispather线程也是在第一次接收外部jvm命令时,进行初始化工作。

Finalizer

这个线程也是在main线程之后创建的,其优先级为10,主要用于在垃圾收集前,调用对象的finalize()方法;关于Finalizer线程的几点:

只有当开始一轮垃圾收集时,才会开始调用finalize()方法;因此并不是所有对象的finalize()方法都会被执行;

该线程也是daemon线程,因此如果虚拟机中没有其他非daemon线程,不管该线程有没有执行完finalize()方法,JVM也会退出;

JVM在垃圾收集时会将失去引用的对象包装成Finalizer对象(Reference的实现),并放入ReferenceQueue,由Finalizer线程来处理;最后将该Finalizer对象的引用置为null,由垃圾收集器来回收;

JVM为什么要单独用一个线程来执行finalize()方法呢?如果JVM的垃圾收集线程自己来做,很有可能由于在finalize()方法中误操作导致GC线程停止或不可控,这对GC线程来说是一种灾难;

Reference Handler

VM在创建main线程后就创建Reference Handler线程,其优先级最高,为10,它主要用于处理引用对象本身(软引用、弱引用、虚引用)的垃圾回收问题。

Monitor Ctrl-Break

用于监控目的,监控Ctrl-Break中断信号的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值