3.1等待/通知机制(wait/notify)

来源:互联网 发布:阿里云和百度云的区别 编辑:程序博客网 时间:2024/05/20 20:21

wait/notify

要点 wait() 执行前 在调用wait()之前,必须先要获得对象锁,即只有在同步方法或者同步代码块中调用wait()方法。 执行作用 wait()使进程进入等待(阻塞状态),在收到通知或者被中断之前都会进入预执行队列。 执行之后1 执行wait()之后,当前线程释放改对象锁,在通知前与其他线程重新竞争资源 执行之后2 执行wait()之后,如果没有使用notify()通知其他线程,即使该对象资源空闲,其他使用过wait()线程由于没有通知会继续阻塞直到这个对象发出notify或者notifyAll / wait()是Object对象的方法。
要点 notify() 执行前 在调用notify()之前,必须先要获得对象锁,即只有在同步方法或者同步代码块中调用notify()方法。 执行作用 通知一个等待该对象资源的线程进入就绪状态,如果有多个线程等待,怎有线程规划器来挑选一个进入就绪状态(区别notify和notifyAll) 执行之后 执行notify之后,当前线程并不会立即释放锁,只有当执行完sychronized方法或者代码块的时候,当前线程才会释放锁 / notify()是Object对象的方法。

wait()之后锁立即释放和notify()之后锁不立即释放

针对上面的锁释放不释放,来做一个小的例子

先做wait()之后锁立即释放

package com.myObject;public class Object1 {    public void mothd1(Object lock) {        synchronized (lock) {            try {                System.out.println("wait begin");                lock.wait();                System.out.println("wait end");            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}
package com.myThread;import com.myObject.Object1;public class Thread1a extends Thread {    Object lock;    Object1 object1 = new Object1();    public Thread1a(Object lock) {        this.lock = lock;    }    @Override    public void run() {        object1.mothd1(lock);    }}
package com.myThread;import com.myObject.Object1;public class Thread1b extends Thread {    Object lock;    Object1 object1 = new Object1();    public Thread1b(Object lock) {        this.lock = lock;    }    @Override    public void run() {        object1.mothd1(lock);    }}
package com.test;import com.myThread.Thread1a;import com.myThread.Thread1b;public class Test1 {    public static void main(String[] args){        Object lock = new Object();        Thread1a thread1a = new Thread1a(lock);        thread1a.start();        Thread1b thread1b = new Thread1b(lock);        thread1b.start();    }}

打印结果

wait begin
wait begin

下面是验证notify()之后锁不立即释放

package com.myObject;public class Object1 {    public void mothd1(Object lock) {        synchronized (lock) {            try {                System.out.println(Thread.currentThread().getName()+" wait begin " + System.currentTimeMillis());                lock.wait();                System.out.println(Thread.currentThread().getName()+" wait end " + System.currentTimeMillis());            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public void mothd2(Object lock) {        synchronized (lock) {            try {                System.out.println(Thread.currentThread().getName()+"notify begin " + System.currentTimeMillis());                lock.notify();                Thread.sleep(5000);//延时用于测试是否有立即释放锁                System.out.println(Thread.currentThread().getName()+"notify end " + System.currentTimeMillis());            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}
package com.myThread;import com.myObject.Object1;public class Thread1a extends Thread {    Object lock;    Object1 object1 = new Object1();    public Thread1a(Object lock) {        this.lock = lock;    }    @Override    public void run() {        object1.mothd1(lock);    }}
package com.myThread;import com.myObject.Object1;public class Thread1b extends Thread {    Object lock;    Object1 object1 = new Object1();    public Thread1b(Object lock) {        this.lock = lock;    }    @Override    public void run() {        object1.mothd2(lock);    }}
package com.test;import com.myThread.Thread1a;import com.myThread.Thread1b;public class Test1 {    public static void main(String[] args) throws InterruptedException{        Object lock = new Object();        Thread1a thread1a = new Thread1a(lock);        thread1a.setName("A");        thread1a.start();        Thread.sleep(1000);        Thread1b thread1b = new Thread1b(lock);        thread1b.setName("B");        thread1b.start();    }}

打印结果

A wait begin 1453090470087
Bnotify begin 1453090471088
Bnotify end 1453090476088
A wait end 1453090476088

说明notify必须在执行完synchronized同步方法或者同步代码块之后才释放锁

wait之后使用interrupt

package com.myObject;public class Object2 {    public void mothd1(Object lock) {        synchronized (lock) {            try {                System.out.println(Thread.currentThread().getName()+" wait begin " + System.currentTimeMillis());                lock.wait();                System.out.println(Thread.currentThread().getName()+" wait end " + System.currentTimeMillis());            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }}
package com.myThread;import com.myObject.Object2;public class Thread2 extends Thread {    Object lock;    Object2 object2 = new Object2();    public Thread2(Object lock) {        this.lock = lock;    }    @Override    public void run() {        object2.mothd1(lock);    }}
package com.test;import com.myThread.Thread2;public class Test2 {    public static void main(String[] args) throws InterruptedException{        Object lock = new Object();        Thread2 thread2 = new Thread2(lock);        thread2.setName("A");        thread2.start();        Thread.sleep(1000);        thread2.interrupt();    }}

当线程处于wait()时,调用线程对象的interrupt()会出现InterruptedException

总结:释放锁的时刻有
1)同步代码完成
2)抛出异常或者return
3)wait()方法

0 0