有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

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

如果上述情况属实,是否有其他方法可以获得线程被阻塞的准确时间


共 (4) 个答案

  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. # 2 楼答案

    是的,这意味着它被屏蔽了0毫秒。i、 e不涉及任何阻碍。线程没有等待监视器锁进入同步块/方法

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

  3. # 3 楼答案

    但是,只有在启动线程之前调用了#setThreadContentionMonitoringEnabled(true)的ThreadMXBean时,线程的阻塞时间(被阻塞)才会返回非零结果。否则,它总是返回零(如果争用监控被禁用,则返回-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
    
  4. # 4 楼答案

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

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