了解java.lang.Thread.State:WAITING(停车)

Leo*_*rdo 82 java multithreading

首先,一个非常愚蠢的问题,我只是想知道等待的"停车"意味着什么?线程是等待停放还是刚停放,因此处于等待状态?当停车发生时,需要多少CPU /内存资源?停放线程的目的是什么?

其次,通过在java线程API中查看park方法

除非许可证可用,否则禁用当前线程以进行线程调度.

如果许可证可用,那么它被消耗并且呼叫立即返回; 否则当前线程因线程调度而被禁用,并且在发生三件事之一之前处于休眠状态.....

英语不是我的主要语言,所以我很难理解,我打算"允许"作为"允许停放线程",所以接下来的问题:

  • 这是什么意思,什么是"许可",以及检查这些许可的人和方式是什么?
  • 这意味着什么:'如果有许可证就可以消费',它是否被"停放"了?
  • 如果第二点是真的,那么'停车'和'休眠'之间的区别是什么?如果我有许可证我可以永久停放,如果没有,我可以让它"休眠"吗?

谢谢

axt*_*avt 32

许可是指继续执行的权限.停车意味着暂停执行,直到获得许可.

Semaphore许可证不同,许可证LockSupport与线程相关联(即允许给予特定线程)并且不会累积(即每个线程只能有一个许可证,当线程消耗许可证时,它会消失).

您可以通过调用给线程许可unpark().线程可以通过调用暂停其执行,直到permit可用(或线程被中断,或超时到期等)park().当许可证可用时,停放的线程使用它并退出park()方法.

  • @Leonardo:这意味着停车后的等待状态. (3认同)
  • 如此反复,如果线程A为线程B调用"停放",但是允许可用,即"B不能停放",那么A发出的呼叫只是返回而B没有停放.否则,当没有许可证时,B必须遵守.那么,等待(停车)是否意味着"A正试图停车,因为我没有许可证,但我现在不能这样做,所以我也阻止A"?抱歉这个长句.我认为这种等待非常耗费资源.我仍然想知道谁在管理整个许可证的事情.谁/什么决定某些线程允许,而其他人不允许. (2认同)
  • @Leonardo:一个线程只能停放自己,没有办法停放其他线程.因此,调用`park()`意味着"我想暂停执行,直到其他一些线程通过调用`unpark()`"给我一个许可. (2认同)

Bad*_*dal 9

根据java Thread State Documentation,一个线程可以进入WAITING状态,原因有三个:

  1. Object.wait没有超时
  2. Thread.join没有超时
  3. LockSupport.park

当您在线程上调用park方法时,除非许可证可用,否则它会禁用线程以进行线程调度.您可以调用unpark方法为给定线程提供许可证(如果尚未提供).

因此,当您的Thread通过LockSupport.park处于WAITING模式时,它将显示为WAITING(停车).

请注意,您只能在当前线程上调用park.这是实现Producer-Consumer Design Pattern的非常有用的机制.


Eug*_*ene 7

让我重新审视这个在阅读文档时无法解决的问题的部分是:

如果许可证可用,那么它就会被消耗并且调用立即返回......

那么,许可证“可用”时,以及如何提供它,以便它可以立即被消耗?找出这一点在某种程度上是微不足道的:

public static void main(String[] args) {

    Thread parkingThread = new Thread(() -> {
        System.out.println("Will go to sleep...");
        sleepTwoSeconds();
        System.out.println("Parking...");
        // this call will return immediately since we have called  LockSupport::unpark
        // before this method is getting called, making the permit available
        LockSupport.park();
        System.out.println("After parking...");
    });

    parkingThread.start();

    // hopefully this 1 second is enough for "parkingThread" to start
    // _before_ we call un-park
    sleepOneSecond();
    System.out.println("Un-parking...");
    // making the permit available while the thread is running and has not yet
    // taken this permit, thus "LockSupport.park" will return immediately
    LockSupport.unpark(parkingThread);

}

private static void sleepTwoSeconds() {
    try {
        Thread.sleep(1000 * 2);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

private static void sleepOneSecond() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}    
Run Code Online (Sandbox Code Playgroud)

代码不言自明,正在thread运行但尚未调用LockSupport.park,而其他一些线程调用LockSupport.unpark它 - 从而使许可证可用。之后我们打电话LockSupport.park,由于许可证可用,所以会立即返回。

一旦你想到这一点,这有点危险,如果你将你的线程暴露给一些你无法控制的代码,并且该代码在LockSupport.unparkpark之后调用 - 它可能不起作用。