您的位置:首页 > 编程语言 > Java开发

Java多线程编程——wait()和notify()、notifyAll()

2017-08-02 18:28 585 查看
1、源码

wait() notify() notifyAll()都是Object类中方法。源码如下所示:

public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait() throws InterruptedException {
wait(0);
}


可以看到它们都是final native修饰的方法。

2、使用条件

首先我们需要明确的一点是wait() notify() notifyAll()都是需要在线程拥有对象锁的情况下使用

在没有对象锁的情况下使用会抛出异常。执行下面代码,会抛出 java.lang.IllegalMonitorStateException 异常

package com.test;

public class Test {
public static void main(String[] args){
try {
Object obj = new Object();
obj.wait();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}




3、作用

3.1 wait()方法的作用

wait()方法能够使当前线程停止,进入阻塞序列,等待被唤醒。

wait()方法被调用后,当前线程会立即释放持有的对象锁。其他线程可以通过竞争的方式获取该对象锁。

唤醒处于阻塞状态的线程,需要其他线程使用notify()或者notifyAll()方法。

3.2 notify()方法的作用

notify()方法能够唤醒处于阻塞状态(处于阻塞队列中)的线程。

需要注意的是调用一次notify()方法只能唤醒一个处于阻塞状态的线程。

而且调用notify()方法后,当前线程不会马上释放锁,被notify 的线程也不会马上获取该对象锁,而是需要等待当前线程执行完同步代码块。

3.3 notifyAll()方法的作用

notifyAll()方法能够唤醒正在等待同意共享资源的所有线程。

4、实例

直接上代码咯。

package com.test;

public class Test3 {

class WaitThread implements Runnable{

private Object lock;

public WaitThread(Object lock) {
// TODO Auto-generated constructor stub
super();
this.lock = lock;
}

@Override
public void run() {
// TODO Auto-generated method stub
try {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() +
" 即将进入阻塞状态  wait time = " + System.currentTimeMillis());
lock.wait();
System.out.println(Thread.currentThread().getName() +
" 结束阻塞状态  wait time = " + System.currentTimeMillis());
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

class NotifyThread implements Runnable{

private Object lock;

public NotifyThread(Object lock) {
// TODO Auto-generated constructor stub
super();
this.lock = lock;
}

@Override
public void run() {
// TODO Auto-generated method stub
try {
synchronized (lock) {
System.out.println(Thread.currentThread().getName() +
" 即将唤醒  notify time = " + System.currentTimeMillis());
lock.notify();
System.out.println(Thread.currentThread().getName() +
" 唤醒线程执行结束  notify time = " + System.currentTimeMillis());
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}

public static void main(String[] args){
try {
Object lock = new Object();
Test3 test3 = new Test3();
Thread waitThread = new Thread(test3.new WaitThread(lock));
waitThread.start();
Thread.sleep(3000);
Thread notifyThread = new Thread(test3.new NotifyThread(lock));
notifyThread.start();
} catch (Exception e) {
// TODO: handle exception
}
}
}




5、总结

1 wait() notify() notifyAll() 方法只能在线程拥有对象锁的时候调用

2 wait()方法调用后 当前线程会立即释放锁

3 notify() notifyAll()方法执行后 当前对象并不会立即释放锁,而是要等同步代码块执行完成后才能释放锁

4 notify()方法每次调用后只能唤醒处于阻塞队列中的一个线程,如果需要唤醒等待当前资源的所有线程需要使用notifyAll()方法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: