资讯专栏INFORMATION COLUMN

一起学并发编程 - sleep与wait的差异

noONE / 570人阅读

摘要:一般差异简单来说,是一个用于线程同步的实例方法。暂停当前线程,不释放任何锁。用来线程间通信,使拥有该对象锁的线程等待直到指定时间或。执行对该对象加的同步代码块。

在JAVA的学习中,不少人会把sleepwait搞混,认为都是做线程的等待,下面主要介绍下这俩者是什么,及了解它们之间的差异和相似之处。

一般差异

简单来说,wait()是一个用于线程同步的实例方法。因为定义在java.lang.Object上,所以它可以在任何对象中调用, 但前提条件是在同步代码块中调用,同时释放对象上的锁,以便另一个线程可以跳入并获取锁。而Thread.sleep()是可以从任何上下文调用的静态方法。Thread.sleep()暂停当前​​线程,不释放任何锁。

主要区别

sleep()线程控制自身流程。wait()用来线程间通信,使拥有该对象锁的线程等待直到指定时间或notify()。

wait()会释放锁和监视器,sleep()不释放任何锁或监视器等。wait()用于线程间通信,而sleep()用于在执行时引入暂停

适用区域,wait只能放在同步语句块中才有意义。

注意事项

wait可以代替sleep吗?

不可以,如果直接调用wait会抛出java.lang.IllegalMonitorStateException异常,原因是还没有得到对象锁,所以无法释放锁。

如何获取锁?

执行对象的synchronized实例方法。

执行对象对应类的synchronized静态方法。

执行对该对象加synchronized的同步代码块。

演示

Thread.sleep

static void method1() {
    synchronized (LOCK) {
        try {
            System.out.println("[" + Thread.currentThread().getName() + "] begin sleep ...");
            Thread.sleep(5_000);
            System.out.println("[" + Thread.currentThread().getName() + "] end sleep ...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) {
    Stream.of("T1", "T2").forEach(name -> new Thread(DifferenceOfWaitAndSleep::method1, name).start());
}

运行此示例一共将一共耗时10S,因T1线程获得锁后会暂停执行,这时候LOCK依旧在T1线程中,然后才会被T2线程获取

[T1] begin sleep ...
[T1] end sleep ...
[T2] begin sleep ...
[T2] end sleep ...

Object.wait

static void method2() {
    synchronized (LOCK) {
        try {
            System.out.println("[" + Thread.currentThread().getName() + "] begin wait ...");
            LOCK.wait();
            System.out.println("[" + Thread.currentThread().getName() + "] end wait ...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) {
    Stream.of("T1", "T2").forEach(name -> new Thread(DifferenceOfWaitAndSleep::method2, name).start());
}

运行此示例会立即输出T1/T2 begin wait ... 但永远不会输出T1/T2 end wait ...,因为没有线程调用LOCK.notify/notifyAll将它们唤醒

[T1] begin wait ...
[T2] begin wait ...
结论

调用:

wait(): 对象调用,当前线程必须在持有锁的对象上进行同步。
sleep(): 线程调用,始终执行的当前线程

同步:

wait(): 同步多个线程同时访问一个对象时
sleep(): 多个线程同步等待线程休眠

锁:

wait(): 释放锁,其它线程有机会执行
sleep(): 持有锁,固定时间后释放或被打断(interrupt)

唤醒条件:

wait(): 直到调用对象的 notify、notifyAll
sleep(): 直到至少时间到期或者调用interrupt()

使用:

sleep(): 用于时间同步
wait(): 用于多线程同步
- 说点什么

全文代码:https://gitee.com/battcn/battcn-concurent/tree/master/Chapter1-1/battcn-thread/src/main/java/com/battcn/chapter8

个人QQ:1837307557

battcn开源群(适合新手):391619659

微信公众号:battcn(欢迎调戏)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67711.html

相关文章

  • 一起并发编程 - 优雅关闭

    摘要:文本将介绍两种可以优雅的终止线程的方式第一种在多线程模式中有一种叫两步终止的模式可以优雅的终止线程,这种模式采用了两个步骤来终止线程,所以叫两步终止模式。 Java中原来在Thread中提供了stop()方法来终止线程,但这个方法是不安全的,所以一般不建议使用。文本将介绍两种可以优雅的终止线程的方式... 第一种 在JAVA《Java多线程模式》中有一种叫Two-Phase Term...

    曹金海 评论0 收藏0
  • java并发编程习之线程生命周期-wait,notify,notifyall(六)

    摘要:不释放持有的锁,释放锁。在调用方法前,必须持有锁,调用唤醒,也要持有锁。休眠一定时间后,进入就绪状态。这两个都能被方法中断当前状态。用法方获取锁判断条件,不满足继续满足执行其他业务方获取锁改变条件通知为什么是而不是会一直循环,直到条件满足。 sleep和wait sleep是Thread类的方法,wait是Object的方法。 sleep可以到处使用,wait必须是在同步方法或者代码...

    Terry_Tai 评论0 收藏0
  • java并发编程习之线程生命周期-interrupt(七)

    摘要:和是配套使用的,方法容易导致死锁。方法不会保证线程的资源正常释放方法给线程打个停止标记,将线程的中断状态设置为,并没有马上强制中断线程,线程是否中断由线程自己决定。终结状态,还是返回。方法判断当前线程是否中断,清除中断标志。 resume、suspend、stop resume和suspend是配套使用的,suspend方法容易导致死锁。 stop方法不会保证线程的资源正常释放 i...

    maxmin 评论0 收藏0
  • 一起并发编程 - 简易线程池实现

    摘要:并且,线程池在某些情况下还能动态调整工作线程的数量,以平衡资源消耗和工作效率。同时线程池还提供了对池中工作线程进行统一的管理的相关方法。 开发中经常会遇到各种池(如:连接池,线程池),它们的作用就是为了提高性能及减少开销,在JDK1.5以后的java.util.concurrent包中内置了很多不同使用场景的线程池,为了更好的理解它们,自己手写一个线程池,加深印象。 概述 1.什么是...

    Harriet666 评论0 收藏0
  • 一起并发编程 - 线程Join分析

    摘要:当时,会进入循环,系统会判断主线程是否处于活跃状态,如果处于活跃状态,主线程就会不停的等待。 由于前段时间比较忙,线程这快学习停滞了,只能利用周日的时间来写写博客了,多线程Join方法的作用就是把指定的线程加入到当前线程,让主线程等待子线程结束之后才能继续运行,从而完成同步操作 介绍 join() 的作用:让主线程等待子线程结束之后才能继续运行,首先先来看下以采集为案例的代码,统计采...

    happen 评论0 收藏0

发表评论

0条评论

noONE

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<