阅读 1196

wait()和sleep()之间的区别? 强烈推荐| Java Debug 笔记

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看活动链接

提问:wait()和sleep()之间的区别??

wait()和之间的sleep()线程有什么区别?

我是否了解wait()-ing线程仍处于运行模式并使用CPU周期,但是sleep()-ing不会消耗任何CPU周期正确吗?

为什么我们都 wait()和sleep():如何实现他们在一个较低的水平有什么不同?

高分回答:

很多的知识点,真的需要写出来才会掌握!!! \color{purple}很多的知识点,真的需要写出来才会掌握!!!{~}

Await可以被另一个notify正在等待等待的监视器调用的线程“唤醒”,而sleep则不能。此外,wait(和notify)必须在synchronized监视对象的块中发生,而sleep不会:

Object mon = ...;
synchronized (mon) {
    mon.wait();
} 
复制代码

此时,当前正在执行的线程将等待并释放监视器。另一个线程可能会做

synchronized (mon) { 
    mon.notify(); 
 }
复制代码

(在同一mon对象上),第一个线程(假设它是监视器上等待的唯一线程)将被唤醒。

您还可以notifyAll在监视器上等待多个线程的情况下进行调用-这将唤醒所有线程。但是,只有一个线程将能够抓住监视器(请记住,它们wait在一个synchronized块中)并继续运行-然后其他线程将被阻塞,直到它们可以获取监视器的锁为止。

另一点是,你叫wait上Object本身(即您等待对象的监视器上),而你打电话sleep的Thread。

另一个问题是,你可以得到虚假唤醒从wait(即线程正在等待简历没有明显的原因)。在某些情况下,您应始终wait按以下步骤旋转:

synchronized {
    while (!condition) { mon.wait(); }
}
复制代码

高分回答

sleep(n)说:“我已经完成了时间片,请在至少n毫秒内不要再给我另一个时间片。” 在请求的时间过去之前,操作系统甚至不会尝试调度休眠线程。

yield()说:“我已经完成了时间片,但是我还有很多工作要做。” 操作系统可以自由地立即给线程另一个时间片,或者给其他线程或处理CPU放弃的收益线程。

wait()说:“我已经完成了时间片。在有人致电notify()之前,不要给我另一个时间片。” 与一样sleep(),除非有人打电话notify()(或发生其他一些唤醒情况之一),否则操作系统甚至不会尝试安排您的任务。

文章翻译自 yl2gl72eozkinivz3vc6swkesy-ac4c6men2g7xr2a-translate.translate.goog/questions/1…

作者建议:第二个回答很有意思,sheep不用cpu,yiedl我一直要,wait我不用。

摘自源码片短:一些核心的定义

 private volatile String name; // 线程的名字
    // 线程的优先级,默认为5,可自行设置,越大代表可以获得的时间片几率越高
    private int       priority; 
​
    /* 是否是守护线程,守护线程在JVM结束时自动销毁 */
    private boolean     daemon = false;
​
    /* 将要运行的目标. */
    private Runnable target;
​
    /* 线程组-就是给线程分组,挺简单,初始化会被分配,与线程池无直接联系 */
    private ThreadGroup group;
    /* 此线程的上下文ClassLoader */
    private ClassLoader contextClassLoader;
​
    /* The inherited AccessControlContext of this thread */
    private AccessControlContext inheritedAccessControlContext;
​
    /* 用于命名是哪个线程的编号 */
    private static int threadInitNumber;
    private static synchronized int nextThreadNum() {
        return threadInitNumber++;
    }
​
    /* 与此线程有关的ThreadLocal值。该映射由ThreadLocal类维护 */
    ThreadLocal.ThreadLocalMap threadLocals = null;
​
    /*
     *与此线程有关的InheritableThreadLocal值。该映射由InheritreadLableThocal类维护.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
​
    /*
    此线程请求的堆栈大小,如果创建者未指定堆栈大小,则为0。
    VM可以根据此数字执行*喜欢的任何事情;一些虚拟机将忽略它.
     */
    private long stackSize;
​
    /*
     * Thread ID
     */
    private long tid;
​
    /* 用于生成线程ID */
    private static long threadSeqNumber;
​
    /* Java thread status 
     */
    private volatile int threadStatus = 0;
复制代码

注意几个重要的方法:

1.有一个start方法,这个方法里面调用了操作系统,利用操作系统去调用我们的run方法。

private native void start0();

  1. interruput方法,这只是一个标志,不会立即中断

interrupted()是静态方法:内部实现是调用的当前线程的isInterrupted(),并且会重置当前线程的中断状态

isInterrupted()是实例方法,是调用该方法的对象所表示的那个线程的isInterrupted(),不会重置当前线程的中断状态

  1. join 面试常问:其实是通过wait来阻塞线程,例如:t1.join(),无限制阻塞t1完成,在继续执行下面的方法。

  2. getAllStackTraces 获取所有线程的堆栈信息,可以用来扩展监控。

其他方法大家看看就行。

下面讲讲线程的状态:

/**
 尚未启动的线程的线程状态
 */
NEW,
​
/**
 可运行线程的线程状态。状态为可运行的线程正在Java虚拟机中执行,
 但是可能正在等待来自操作系统的其他资源,例如处理器。
 */
RUNNABLE,
​
/**
 线程的线程状态被阻塞,等待监视器锁定。处于阻塞状态的线程正在等待监视
 器锁定输入同步块/方法或调用Object.wait后重新输入同步块/方法。
 区别就是有个while
 */
 //  synchronized(this)
//  {
//    while (flag)
//    {
//      obj.wait();
//    }
//  }
BLOCKED,
​
/**
 *等待线程的线程状态。由于调用以下其中一种方法,线程处于等待状态:
 Object.wait无超时
 Thread.join没有超时
 LockSupport.park 等待状态
 正在等待另一个线程执行特定操作。例如,在某个对象上调用
 Object.wait()的线程正在等待另一个线程调用 Object.notify()
 或该对象上的Object.notifyAll()名为 Thread.join的线程正在等待指定
 的线程终止。
 */
WAITING,
​
/**
 具有指定等待时间的等待线程的线程状态。线程由于以指定的正等待时间调用以下
 方法之一而处于定时等待状态:
 Thread.sleep,
 Object.wait(long)
 Thread.join(long)
 LockSupport.parkNanos
 LockSupport.parkUntil
 */
TIMED_WAITING,
​
/**
 终止线程的线程状态。*线程已完成执行
 */
TERMINATED;
​
复制代码

多了解,很有用的,方便查看线程的堆栈日志。

欢迎关注我的专栏StackOverFlow,我会筛选优质的问答,面试常考!!! \color{red}欢迎关注我的专栏StackOverFlow,我会筛选优质的问答,面试常考!!!{~}

有最新、优雅的实现方式,我也会在文末写出我对本问答的见解 \color{red}有最新、优雅的实现方式,我也会在文末写出我对本问答的见解{~}

真心感谢帅逼靓女们能看到这里,如果这个文章写得还不错,觉得有点东西的话

求点赞👍 求关注❤️ 求分享👥 对8块腹肌的我来说真的 非常有用!!!

如果本篇博客有任何错误,请批评指教,不胜感激 !❤️❤️❤️❤️

文章分类
后端
文章标签