Java线程中的wait(),notify()与sleep()

在Java中可以通过wait()与notify()或notifyAll()实现线程协作。简要总结有如下几点:
1.wait()让线程进入等待状态,并释放锁(而sleep等待的同时并不释放锁)
2.notify()通知wait的线程尝试获取对象锁,在此线程任务执行完后,wait的线程就会重新获得锁,继续运行。
3.wait与notify均是Object的方法,调用这两个方法需要在synchronized代码块或函数中执行,否则会抛出异常。

下面通过一些代码来验证。

public class TestAlpha {

    Object mLock = new Object();

    Runnable mRunnableOne = new Runnable() {
        @Override
        public void run() {
            try {
                // 由于没有在synchronized块中调用,会抛出异常
                mLock.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };

    public static void main(String[] args){
        TestAlpha test = new TestAlpha();

        Thread threadOne = new Thread(test.mRunnableOne);
        threadOne.start();
    }

}

首先这段代码开启一个线程并执行wait,由于并没有在synchronized块中执行,因此会直接抛出错误:

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at com.example.threadtest.TestAlpha$1.run(TestAlpha.java:11)
    at java.lang.Thread.run(Thread.java:745)

接下来添加一些打印,并将wait调用放到synchronized代码块中:

Runnable mRunnableOne = new Runnable() {
    @Override
    public void run() {
        synchronized (mLock) {
            try {
                System.out.println("ThreadOne start");
                mLock.wait();
                System.out.println("ThreadOne end");    // 此行不会打印
            } catch (InterruptedException e) {
                    e.printStackTrace();
            }
        }
    }
};

由于wait后没有其他线程调用notify,因此这个线程一直在等待状态,后面的打印也就无法执行了。

下面开启另一个线程,调用notify函数:

public class TestAlpha {

    Object mLock = new Object();

    Runnable mRunnableOne = new Runnable() {
        @Override
        public void run() {
            synchronized (mLock) {
                try {
                    System.out.println("ThreadOne start");
                    mLock.wait();
                    System.out.println("ThreadOne end");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    Runnable mRunnableTwo = new Runnable() {
        @Override
        public void run() {
            synchronized (mLock) {
                try {
                    System.out.println("ThreadTwo start");
                    // 运行1s后触发notify调用
                    Thread.sleep(1000);
                    mLock.notify();
                    System.out.println("ThreadTwo end");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    public static void main(String[] args) {
        TestAlpha test = new TestAlpha();

        Thread threadOne = new Thread(test.mRunnableOne);
        threadOne.start();

        Thread threadTwo = new Thread(test.mRunnableTwo);
        threadTwo.start();
    }

}

可以看到程序输出:

ThreadOne start
ThreadTwo start
ThreadTwo end
ThreadOne end

第二个线程调用notify后,并且执行完后序代码,线程一就会重新获得对象锁,并继续执行。可以在第二个线程nofity后加入更多耗时操作进一步验证。

再接下来,将线程一中的wait换成Thread.sleep(),例如设定等待10s。

Runnable mRunnableOne = new Runnable() {
    @Override
    public void run() {
        synchronized (mLock) {
            try {
                System.out.println("ThreadOne start");
                Thread.sleep(10000);
                System.out.println("ThreadOne end");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
};

这样情况下,由于线程一在等待时没有释放锁,因此线程二不能执行synchronized中的内容,只能等待线程一结束后再运行。

ThreadOne start
ThreadOne end
ThreadTwo start
ThreadTwo end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值