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()方法