使用ThreadMXBean更精确地评估Thread占用时间

本文介绍了一种在Java中更精确地测量程序运行时间的方法,利用ThreadMXBean接口获取当前线程的CPU时间,对比使用System.currentTimeMillis()的传统方式,提供了一个具体的测试案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需要评估某个程序运行消耗的时间时,一般情况下在JAVA中使用System.currentTimeMillis()来记录当前的时间,运行后再次采集一次当前时间,将两者的差作为运行消耗的时间。但这个时间并不是十分的精确,因为在程序运行的过程中,可能发生系统进程切换等系统事件,这部分时间也被计算在这个消耗时间里。

而Java 虚拟机实现可能提供了支持测量当前线程的 CPU 时间的功能。ThreadMXBean接口提供了线程时间管理、争用监视等功能,使用前应先确定该JDK实现,提供了这方面的功能。isThreadCpuTimeSupported() 方法可以用于确定 Java 虚拟机是否支持测量任何线程的 CPU 时间。isCurrentThreadCpuTimeSupported() 方法可以用于确定 Java 虚拟机是否支持测量当前线程的 CPU 时间。支持任何线程 CPU 时间测量的 Java 虚拟机实现也支持当前线程的 CPU 时间测量。通过调用 ManagementFactory.getThreadMXBean() 方法获得ThreadMXBean的实现。

封装的获取时间的方法 :

/** Get CPU time in nanoseconds. */

    public static long getCpuTime () {

        ThreadMXBean bean = ManagementFactory.getThreadMXBean();

        return bean.isCurrentThreadCpuTimeSupported() ? bean

                .getCurrentThreadCpuTime() : 0L;

    }

     /** Get user time in nanoseconds. */

    public static long getUserTime () {

        ThreadMXBean bean = ManagementFactory.getThreadMXBean();

        return bean.isCurrentThreadCpuTimeSupported() ? bean

                .getCurrentThreadUserTime() : 0L;

    }

测试例子:

  Thread t1 = new Thread(new Runnable() {

            @Override

            public void run () {

                try {

                    for (;;) {

                        long start = getUserTime();

                        //long start = System.currentTimeMillis();

                        System.out.println("T1 Start: " + start);

                        for (int i = 0; i < 900000000; i++) {

                            for (int j = 0; j < 10000000; j++) {

                            }

                        }

                        Thread.sleep(2);

                        long now = getUserTime();

                        // long now = System.currentTimeMillis();

                        System.out.println("T1 End: " + now);

                        System.out.println("Thread 1, const(milli Sec): "

                                + (now - start) / 1000000);

                        Thread.sleep(2000);

                    }

                }

                catch (Exception e) {

                    e.printStackTrace();

                }

            }

        });

 Thread1会定期输出两个for循环所消耗的时间。

 Thread t2 = new Thread(new Runnable() {

            @Override

            public void run () {

                try {

                    boolean runned = false;

                    for (;;) {

                        long start = getUserTime();

                        System.out.println("T2 Start: " + start);

//                        if (!runned) {

//                            for (int i = 0; i < 900000000; i++) {

//                                for (int j = 0; j < 10000000; j++) {

//                                }

//                            }

//                            runned=true;

//                        }

                        Thread.sleep(500);

                        long now = getUserTime();

                        System.out.println("T2 End: " + now);

                        System.out.println("Thread 2, const(milli Sec): "

                                + (now - start) / 1000000);

                    }

                }

                catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        });

Thread2 输出的T2 Start、T2 End永远都是0。因为Thread2 只是暂停了线程,并没有做任何逻辑运算,因此这个线程实际上并没有占用时间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值