it-swarm.cn

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

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

二,通过查看 Java thread API 中的park方法_

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

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

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

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

谢谢

79
Leonardo

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

Semaphorename__ 的许可不同,LockSupportname__的许可与线程相关联(即许可被赋予特定线程)并且不会累积(即每个线程只能有一个许可,当线程消耗许可时,它消失)。

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

31
axtavt

根据Java 线程状态文档 ,线程可以进入WAITING状态有三个原因:

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

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

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

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

9
Badal

从类描述(在 LockSupport javadoc 的顶部)描述许可证:

该类与使用它的每个线程相关联,a permit (在Semaphore类的意义上)。如果许可证可用,将立即返回停车呼叫,在此过程中消耗[许可证];否则[呼叫停车]可能阻止。如果尚未提供许可证,则拨打unpark会使许可证可用。 (与信号量不同,许可证不会累积。最多只有一个。)

(我扩展了[text],使非英语人士更容易阅读。)

希望有更深入了解的人可以详细说明这一点。 见axtavt的答案。

最后一点,来自javadoc的最终引用:

这些方法旨在用作创建更高级别同步实用程序的工具,并且对于大多数并发控制应用程序本身并不有用。

2
Charles Goodwin

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

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

那么许可证是如何“可用的”,是谁以及如何使其可用,以便它可以立即被消费?这在某种程度上是微不足道的:

private static void sleep(long howMuch) {
    try {
        Thread.sleep(howMuch);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public static void main(String[] args) {

    Thread t = new Thread(() -> {
        System.out.println("Sleeping...");
        sleep(2000);
        System.out.println("Parking");
        LockSupport.park();
        System.out.println("After parking");
    });

    sleep(1000);
    t.start();
    System.out.println("Unparking");
    // making the permit available while the thread is running and has not yet
    // taken this permit, thus "LockSupport.park" will return immediately
    LockSupport.unpark(t);

}

代码说明了一点,threadname__正在运行 但尚未 称为LockSupport.park,而其他一些线程则调用LockSupport.unpark - 从而使许可可用。之后我们调用LockSupport.park并且因为许可证可用而立即返回。

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

1
Eugene

据我了解,“许可”只是一个对象,表示一个线程是否可以“取消停放”。这是由线程本身(或当您尝试停放线程时de JRE)检查“被消耗”的东西,我知道许可证消失并且线程不会被禁止。

我认为你应该多学习多线程。把它想象成一个叫做“许可”的对象的分配器。你告诉一个线程停放,并且线程检查分配器,如果有“许可”,则线程接受并离开(没有停放)。如果分配器中没有“许可证”,则停止螺纹直到“许可”可用(并且您可以在unpark中将“许可”放入分配器中。

至于CPU /内存使用情况,我认为这取决于操作系统等...

0
Vic