java多线程应用程序:获取线程阻塞时间

时间:2011-03-23 04:20:26

标签: java multithreading

我在工作线程死亡之前调用threadInfo.getBlockedCount()getBlockedTime()。 我得到的阻止计数为1,但阻塞时间为0。 这是否意味着线程被阻止但阻塞时间小于一毫秒?

如果上述情况属实,是否有另一种方法可以获得线程被阻止的准确时间?

4 个答案:

答案 0 :(得分:2)

但是,如果在*启动线程之前调用ThreadMXBean#setThreadContentionMonitoringEnabled(true),则线程的阻塞时间(被阻塞)似乎只返回非零结果。否则,它总是返回零(如果禁用争用监视,则返回-1)。下面的代码演示了这个:

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

public class BlockedTimeMain {
    public static void main(String[] _) throws InterruptedException  {
        ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
        final Object lock = new Object();

        Thread t = new Thread("Foo") {
            @Override public void run() {
                // This will block forever
                synchronized(lock) {
                    // Will never get here
                    System.out.println("Got the lock from " + Thread.currentThread());
                }
            }
        };
        synchronized(lock) {
            t.start();
            mbean.setThreadContentionMonitoringEnabled(true);
            for (int i=0; i < 5; i++) {
                ThreadInfo[] tis = mbean.getThreadInfo(new long[]{t.getId()}, true, true);
                ThreadInfo ti = tis[0];

                if (ti.getThreadId() != t.getId())
                    throw new AssertionError("Unexpected " + t.getId() + " vs " + tis[0].getThreadId());

                System.out.println(t + " " + ti.getThreadState() 
                        + ": blockedTime=" + ti.getBlockedTime() + "/" + ti.getBlockedCount() 
                        + ", waitTime" + ti.getWaitedTime() + "/" + ti.getWaitedCount());
                Thread.sleep(1000);
            }
        }
        System.exit(0);
    }
}

示例输出:

Thread[Foo,5,main] BLOCKED: blockedTime=0/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=0/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=0/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=0/1, waitTime0/0

答案 1 :(得分:1)

可以测试一下,例如:

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;

public class BlockedTimeMain {
    public static void main(String[] _) throws InterruptedException  {
        ThreadMXBean mbean = ManagementFactory.getThreadMXBean();
        mbean.setThreadContentionMonitoringEnabled(true);
        final Object lock = new Object();

        Thread t = new Thread("Foo") {
            @Override public void run() {
                // This will block forever
                synchronized(lock) {
                    // Will never get here
                    System.out.println("Got the lock from " + Thread.currentThread());
                }
            }
        };
        synchronized(lock) {
            t.start();
            for (;;) {
                ThreadInfo[] tis = mbean.getThreadInfo(new long[]{t.getId()}, true, true);
                ThreadInfo ti = tis[0];

                if (ti.getThreadId() != t.getId())
                    throw new AssertionError("Unexpected " + t.getId() + " vs " + tis[0].getThreadId());

                System.out.println(t + " " + ti.getThreadState() 
                        + ": blockedTime=" + ti.getBlockedTime() + "/" + ti.getBlockedCount() 
                        + ", waitTime" + ti.getWaitedTime() + "/" + ti.getWaitedCount());
                Thread.sleep(1000);
            }
        }
    }
}

示例输出:

Thread[Foo,5,main] BLOCKED: blockedTime=2/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=1007/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=2012/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=3016/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=4021/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=5025/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=6028/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=7032/1, waitTime0/0
Thread[Foo,5,main] BLOCKED: blockedTime=8035/1, waitTime0/0

答案 2 :(得分:0)

是的,它确实意味着它被阻止了0毫秒。即没有涉及阻塞。线程没有等待监视器锁进入同步块/方法。

您看到这一点是因为您必须编写一个包含一个或两个线程的简单程序,并且没有延迟。 你需要在线程上引入非常重的负载才能真正看到正值。

答案 3 :(得分:0)

显然,这就是它的意思,显然没有办法让时间更精确。 (javadocs表示阻塞时间可能测量并且(可能)以更高的精度累积,但ThreadInfo API不会公开此信息,并且似乎没有任何其他犹太方式得到它。)

我说“显然”,因为javadoc实际上将时间值描述为“近似累计经过时间”。这留下了这可能是非常粗略的近似的可能性,可能与System.getCurrentTimeMillis()返回的时钟值具有相同的粒度。此外,它没有说明在转换为毫秒值时,使用高精度定时器测量的累计时间是否会被舍入或截断;即零是否意味着“小于1毫秒”或“小于0.5毫秒”。