如何获取在JVM中运行的java程序(单线程或多线程)的CPU时间?

时间:2017-11-29 22:41:09

标签: java jvm

在此post中,使用挂钟时间定时任务不正确

  

"挂钟时间"是等待任务完成的用户所经历的实际经过时间。在Java 1.5之前,测量挂钟时间是对Java任务进行基准测试的常规(且唯一)方法。

     

要测量挂钟时间,请在任务之前和之后拨打java.lang.System . currentTimeMillis()并取消差异。   该方法以毫秒(千分之一秒)返回时间。

     

挂钟时间受到系统上其他活动的强烈影响,例如后台进程,其他应用程序,磁盘或网络活动以及显示更新。在某些系统(如Windows)上,如果应用程序不在顶部,它将以较低优先级运行并需要更长时间。所有这些都可能会影响您的基准测试结果,除非您非常小心地使用卸载的系统并在大量测试中取平均值。

     

如果您对用户体验的内容感兴趣,使用挂钟时间并不一定是坏事。但这使得很难获得一致的基准数字来揭示您自己的应用程序的问题。

如果我们使用getProcessCpuTime(),似乎我们会测量JVM的所有时间。

那么如何区分JVM内在线程(below)和java程序线程(单线程还是多线程)以便我可以测量真正的Java程序线程CPU时间?

  enum ThreadType {   //  **intrinsic threads**
    vm_thread,
    cgc_thread,        // Concurrent GC thread
    pgc_thread,        // Parallel GC thread
    java_thread,       // Java, CodeCacheSweeper, JVMTIAgent and Service threads.
    compiler_thread,
    watcher_thread,
    os_thread
  };

在此post中,main_thread似乎是一个单独的主题。 是由JVM创建的mutator线程吗?src/share/vm/runtime/thread.cpp

3191   // Attach the main thread to this os thread
3192   JavaThread* main_thread = new JavaThread();
3193   main_thread->set_thread_state(_thread_in_vm);
3194   // must do this before set_active_handles and initialize_thread_local_storage
3195   // Note: on solaris initialize_thread_local_storage() will (indirectly)
3196   // change the stack size recorded here to one based on the java thread
3197   // stacksize. This adjusted size is what is used to figure the placement
3198   // of the guard pages.
3199   main_thread->record_stack_base_and_size();
3200   main_thread->initialize_thread_local_storage();

如果Java程序是多线程的,如下所示,该怎么办?

// Java code for thread creation by implementing
// the Runnable Interface
class MultithreadingDemo implements Runnable
{
    public void run()
    {
        try
        {
            // Displaying the thread that is running
            System.out.println ("Thread " +
                    Thread.currentThread().getId() +
                    " is running");

        }
        catch (Exception e)
        {
            // Throwing an exception
            System.out.println ("Exception is caught");
        }
    }
}
int n = 8; // Number of threads
for (int i=0; i<8; i++)
{
    Thread object = new Thread(new MultithreadingDemo());
    object.start();
}    

为什么MXBeans只返回1个主线程?

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.ArrayDeque;
import java.util.LinkedList;

public class MultiThread {
    /** Get CPU time in nanoseconds. */
    public long getCpuTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
                bean.getCurrentThreadCpuTime( ) : 0L;
    }
    /** Get user time in nanoseconds. */
    public long getUserTime( ) {
        ThreadMXBean bean = ManagementFactory.getThreadMXBean( );
        return bean.isCurrentThreadCpuTimeSupported( ) ?
                bean.getCurrentThreadUserTime( ) : 0L;
    }

    public static void main(String[] args) {

        // deque operation
        //ArrayDeque<LinkedList<Integer>> deque = new ArrayDeque<LinkedList<Integer>>();
        ArrayDeque<Byte[]> deque = new ArrayDeque<Byte[]>();
        int objectSize = 1024;
        int xxx = 0;

        // expand old and young heap size
        for(long i = 0; i < 1500; i++){
            for(int j = 0; j < 300; j++){
                deque.addLast(new Byte[objectSize]);
            }
            for(int m = 0; m < 65535; m++){
                xxx += 1;
                xxx -= 1;
            }
            for(int j = 0; j < 20; j++){
                deque.removeLast();
            }
        }

        for(long i = 0; i < 1500; i++){
            for(int j = 0; j < 300; j++){
                deque.addLast(new Byte[objectSize]);
            }
            for(int m = 0; m < 65535; m++){
                xxx += 1;
                xxx -= 1;
            }
            for(int j = 0; j < 300; j++){
                deque.removeFirst();
            }
        }

        int n = 8; // Number of threads
        for (int i=0; i<8; i++)
        {
            Thread object = new Thread(new MultithreadingDemo());
            object.start();
        }

        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        //don't need monitor and synchronizer info,only get thread and stack info。
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
        for (ThreadInfo threadInfo : threadInfos) {
            String tName = threadInfo.getThreadName();
            long tId = threadInfo.getThreadId();
            System.out.println(tName + "," + tId);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

  

为什么MXBeans只返回1个主线程?

因为您在调用ThreadMXBean时使用getCurrentThreadCpuTime测量CPU周期来调用(当前)线程。它完全按照它在tin上所说的那样,如果你想测量你选择测量的特定线程花费了多少CPU时间,同时排除其他线程,这非常有用。它提供了您要求的粒度。

  

MultiThread

即使编译也没有,你至少应该在提出问题时努力发布一些真实的代码。