【6.20】sleep()和wait()的区别

sleep()和wait()的区别

1、wait()方法

1.1使用场景

当某个线程获取到锁后,却还是不满足执行的条件,就可以调用对象锁的wait方法,进入等待状态。

直到外在条件满足了,就可以由其它线程调用notify或者notifyAll方法,来唤醒这个线程。

1.2条件

只有已经获取锁的线程,才可以调用锁的wait、notify方法,否则会抛出IllegalMonitorStateException异常。

看如下代码:

@Log4j
public class WaitTest {
 
    public static void main(String[] args) {
        Object lock = new Object();
        Thread threadA = new Thread(() -> {
            synchronized (lock) {
                log.info("获取了锁");
                try {
                    log.info("休眠一会儿");
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.info("调用wait..");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
                log.info("被唤醒");
            }
        }, "A");
        threadA.start();
 
        lock.notify();
 
    }
}

输出为:

【6.20】sleep()和wait()的区别_第1张图片

这是因为:线程A获得锁之后,主动调用wait方法释放了锁和CPU资源,陷入阻塞状态。主线程在没获得锁的情况下,调用notify方法,会抛出异常。

再看如下代码:

@Log4j
public class WaitTest {
 
    public static void main(String[] args) {
        Object lock = new Object();
        Thread threadA = new Thread(() -> {
            synchronized (lock) {
                log.info("获取了锁");
                try {
                    log.info("休眠一会儿");
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.info("调用wait..");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
                log.info("被唤醒");
            }
        }, "A");
        threadA.start();
 
        Thread threadB = new Thread(()->{
            synchronized (lock) {
                log.info("获得了锁");
 
                log.info("叫醒A");
                lock.notify();
            }
        }, "B");
        threadB.start();
    }
}

输出为:

【6.20】sleep()和wait()的区别_第2张图片

这是因为:线程A调用wait方法主动释放锁,线程B获得了锁,调用了notify方法,才能叫醒线程A。

线程正常运行时的状态是Runnable,调用wait方法之后,变为Waiting状态。那么主动Waiting的线程,被唤醒后,状态一定会由Waiting变为Runnable吗?

答案是不一定的。

看如下代码:

@Log4j
public class WaitTest {
 
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        Thread threadA = new Thread(() -> {
            synchronized (lock) {
                log.info("获取了锁");
                try {
                    log.info("休眠一会儿");
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.info("调用wait..");
                try {
                    log.info("wait前的线程状态" + Thread.currentThread().getState());
                    lock.wait();
                    log.info("wait后的线程状态" + Thread.currentThread().getState());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
                log.info("被唤醒");
            }
        }, "A");
        threadA.start();
 
        TimeUnit.SECONDS.sleep(2);
 
        Thread threadB = new Thread(()->{
            synchronized (lock) {
                log.info("获得了锁");
                log.info("叫醒A前,A的状态" + threadA.getState());
                log.info("叫醒A");
                lock.notify();
                log.info("发现还有很多事需要做,先不释放锁");
                log.info("我在做事过程中,A的状态: " + threadA.getState());
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.info("我做完了");
            }
        }, "B");
        threadB.start();
    }
}

输出为:

【6.20】sleep()和wait()的区别_第3张图片

这是因为:线程B调用notify方法后,没有立刻将线程的控制器交出去,线程A被唤醒后,会先变为Blocked,参与锁的竞争,成功竞争到锁后,才会向下执行。

被唤醒的线程需要重新参与锁竞争。

1.2sleep()方法

作用:让当前线程进入指定的休眠时间(单位是毫秒),进入阻塞状态,放弃占有CPU时间片,让给其它线程使用。

public class ThreadTest06 {
    public static void main(String[] args) {
        //让当前线程(主线程)进入休眠,睡眠5秒
        try {
            Thread.sleep(1000*5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

		//5秒之后执行这里的代码
        System.out.println("hello world!");
    }
}

sleep()和wait()的区别

1.sleep属于Thread类;wait属于Object类

2.sleep不会释放锁,也不需要占用锁;wait会释放锁

3.sleep可以在任何地方使用,wait只能在同步方法或同步控制块中使用

你可能感兴趣的:(log4j,java,jar)