java多线程之wait()和sleep()的区别

2018-06-27  本文已影响62人  一个菜鸟JAVA
1.方法所属不同

wait()是Object上的方法,而sleep()是属于Thread上的方法

2.锁对象释放与否

sleep()方法导致了程序暂停执行指定的时间,让出cpu给其他线程,但是他的监控状态依然保持者,
当指定的时间到了又会自动恢复运行状态。
重点:不会释放锁对象
wait()线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()或者notifyAll()
方法后本线程才进入对象锁定池准备.
重点:会释放锁对象
下面给出测试代码:

package com.zc.thread;

/**
 * Created by zengchao 
 */
public class App {
    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        //sleep()
        new Thread(new A(lock)).start();
        Thread.sleep(1000L);
        new Thread(new B(lock)).start();
        //wait()
//        new Thread(new C(lock)).start();
//        Thread.sleep(1000L);
//        new Thread(new D(lock)).start();
    }

    private static class A extends Thread{
        private Object lock;

        public A(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            synchronized (lock){
                System.out.println("线程A获取到锁,进入5秒睡眠");
                try {
                    Thread.sleep(5000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程A执行完成");
            }
        }
    }

    private static class B extends Thread{
        private Object lock;
        public B(Object lock) {
            this.lock = lock;
        }
        @Override
        public void run() {
            synchronized (lock){
                System.out.println("线程B获取到锁");
                System.out.println("线程B完成");
            }
        }
    }

    private static class C extends Thread{
        private Object lock;

        public C(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            synchronized (lock){
                System.out.println("线程C获取到锁");
                System.out.println("线程C调用wait,释放锁");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("线程C执行完成");
            }
        }
    }

    private static class D extends Thread{
        private Object lock;

        public D(Object lock) {
            this.lock = lock;
        }

        @Override
        public void run() {
            synchronized (lock){
                System.out.println("线程D获取到锁");
                System.out.println("线程D执行完成,调用notify()唤醒线程C");
                lock.notify();
            }
        }
    }
}

第一次执行

        Object lock = new Object();
        //sleep()
        new Thread(new A(lock)).start();
        Thread.sleep(1000L);
        new Thread(new B(lock)).start();

结果:

线程A获取到锁,进入5秒睡眠
线程A执行完成
线程B获取到锁
线程B完成

当线程A获取到锁后,进入5秒睡眠,但是线程A任然没有释放锁,所以线程B只能等待锁,而无法运行.而当线程A执行完成之后,
释放了锁,所以B就可以执行了.

第二次执行

        Object lock = new Object();
        //wait()
        new Thread(new C(lock)).start();
        Thread.sleep(1000L);
        new Thread(new D(lock)).start();

结果:

线程C获取到锁
线程C调用wait,释放锁
线程D获取到锁
线程D执行完成,调用notify()唤醒线程C
线程C执行完成

首先线程C获取到了锁,然后调用wait()方法,C线程释放锁,D线程获取到锁,执行完成之后,调用notify()唤醒C线程,C线程继续执行.
如果D线程不调用notify(),那么线程C则一直处于wait中,结果线程C执行完成不会打印出结果,程序也不会终止.

总结

上述是个人整理出来的,不正确的地方还请各位指正.第一点其实无关紧要,最重要记住第二点即可.

上一篇下一篇

猜你喜欢

热点阅读