为什么单线程java程序有这么multithreading?

我有一个java程序,它有13个线程,虽然其中只有一个是99%的CPU使用率,并且已经运行了大约24小时。 其他人的使用率为0.0%,显示TIME+0:00.00:12.82 ,其中一个为3:51.48 。 该程序旨在成为单线程程序,所以我想知道为什么其他线程在那里?

他们在做什么,为什么他们显示如此少的CPU使用和TIME +?

更新:我有一个我写的旧java程序(第一个程序 – 不要评判我!),这是单线程并显示相同类型的线程使用…

 import java.io.*; class xdriver { static int N = 100; static double pi = 3.141592653589793; static double one = 1.0; static double two = 2.0; public static void main(String[] args) { //System.out.println("Program has started successfully\n"); if( args.length == 1) { // assume that args[0] is an integer N = Integer.parseInt(args[0]); } // maybe we can get user input later on this ... int nr = N; int nt = N; int np = 2*N; double dr = 1.0/(double)(nr-1); double dt = pi/(double)(nt-1); double dp = (two*pi)/(double)(np-1); System.out.format("nn --> %d\n", nr*nt*np); if(nr*nt*np < 0) { System.out.format("ERROR: nr*nt*np = %d(long) which is %d(int)\n", (long)( (long)nr*(long)nt*(long)np), nr*nt*np); System.exit(1); } // inserted to artificially blow up RAM double[][] dels = new double [nr*nt*np][3]; double[] rs = new double[nr]; double[] ts = new double[nt]; double[] ps = new double[np]; for(int ir = 0; ir < nr; ir++) { rs[ir] = dr*(double)(ir); } for(int it = 0; it < nt; it++) { ts[it] = dt*(double)(it); } for(int ip = 0; ip < np; ip++) { ps[ip] = dp*(double)(ip); } double C = (4.0/3.0)*pi; C = one/C; double fint = 0.0; int ii = 0; for(int ir = 0; ir < nr; ir++) { double r = rs[ir]; double r2dr = r*r*dr; for(int it = 0; it < nt; it++) { double t = ts[it]; double sint = Math.sin(t); for(int ip = 0; ip < np; ip++) { fint += C*r2dr*sint*dt*dp; dels[ii][0] = dr; dels[ii][1] = dt; dels[ii][2] = dp; } } } System.out.format("N ........ %d\n", N); System.out.format("fint ..... %15.10f\n", fint); System.out.format("err ...... %15.10f\n", Math.abs(1.0-fint)); } } 

引用此处进行的讨论和其他研究。

几个核心JVM线程:

  1. Attach Listener:这是一个总是侦听其他JVM线程发送请求的线程。 一个实际的例子是在分析或(我不是这个)生产级应用程序监视工具如DynaTrace的情况下。
  2. 信号调度程序:当操作系统向JVM发出信号时,信号调度程序线程会将信号传递给适当的处理程序。
  3. 引用处理程序:用于将待处理引用排入队列的高优先级线程。 GC创建一个简单的链接引用列表,需要进行处理,并且该线程会快速将它们添加到正确的队列中,并通知ReferenceQueue侦听器。
  4. 终结器:终结器线程调用终结器方法。
  5. DestroyJavaVM:该线程在程序退出时卸载Java VM。 大多数时候它应该等待。
  6. 垃圾收集器:负责Java的垃圾收集机制的线程,具体取决于GC是否启用。
  7. main:运行包含main方法的程序的主线程。

需要注意的一点是,它将依赖于JVM实现它将启动多少以及所有核心线程,但即使Java程序被编写为单线程,JVM中也会有多个线程。

Java程序可以是单线程的,但JVM(将运行用户定义的Java程序)是multithreading的,并且即使从一开始就具有(至少对于最新的JVM)多个线程。

下面是运行单线程Java程序的Java HotSpot(TM)客户端VM版本24.55-b03的快照:

回答你的问题

他们在做什么,为什么他们显示如此少的CPU使用和TIME +?

什么部分: JVM开始有一个目的,如上所述,如果任何分析或监视程序想要从JVM获取某些细节,JVM想要监听。
为什么部分:因为它们真的没有活动或正在运行,它们处于等待或停放状态(参见我附加快照中的黄色线程,如果你有一个GUI监控应用程序,那么你也应该看到黄色,否则命令行然后线程进入WAIT状态)因此它们不占用任何或最少的CPU周期,因此CPU使用率较低。 TIME+会再次显示它们处于活动状态的时间,因为它们不是,所以此参数也较少。

希望这可以帮助!

在此处输入图像描述

启动Java程序意味着启动JVM并告诉它要运行哪个主类(通常具有静态main方法)。

除了上面提到的主线程之外,这个JVM还会生成几个后台线程。

其中有

  • VM线程 :一个观察线程,等待要求VM处于安全点的任务。 例如,有一个完全“阻止世界”的垃圾收集任务。 但还有其他人。
  • GC线程 :维护几个线程来运行垃圾回收。
  • 编译线程 :这些线程用于将字节代码编译为本机机器代码。

可能还有更多。

此外,如果您使用的是AWT或Swing,您将从这些框架中获得更multithreading。 其中之一就是所谓的事件调度员(EDT)。 而且 – 当然 – 可能有你创建和运行的线程:定时器,执行器,或者只是一些任意线程。 即使对于简单的hello world应用程序,也可能有十几个线程在运行。

但是大多数这些线程比做某事更等待。 所以很有可能只有一个线程正在工作,因此利用了一些CPU。

虽然…… 100%的CPU利用率可能是某些问题的指标。 例如,一个永无止境的循环。 您必须使用分析器来查找实际发生的情况。 但它可能只是一个具有这种CPU利用率的程序。 你的判断。

很可能线程已在某处创建并且从未使用过。

例如:

 ExecutorService es = Executors.newFixedThreadPool(12); // burn cpu, using only one thread (main) int i = 0; while(true) { i++; } 

TIME+ from top是花费的CPU时间。 一种解释是,如果一个进程持续阻塞或者总是被阻塞,那么它将具有低CPU使用率和低TIME+