一、方法wait()锁释放,notify()锁不释放
(一)wait()锁释放的案例
package com.it.po.thread8; public class Service1 { public void methodA(Object lock){ synchronized (lock){ try { System.out.println("线程 "+Thread.currentThread().getName()+" begin wait"); lock.wait(); System.out.println("线程 "+Thread.currentThread().getName()+" end wait"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
package com.it.po.thread8; public class MyThread4_1 extends Thread { private Object lock; public MyThread4_1(Object lock) { this.lock = lock; } @Override public void run() { super.run(); new Service1().methodA(lock); } }
package com.it.po.thread8; public class MyThread4_2 extends Thread { private Object lock; public MyThread4_2(Object lock) { this.lock = lock; } @Override public void run() { super.run(); new Service1().methodA(lock); } }
package com.it.po.thread8; import java.security.acl.LastOwnerException; public class Run5 { public static void main(String[] args) throws InterruptedException { Object lock = new Object(); MyThread4_1 my1 = new MyThread4_1(lock); MyThread4_2 my2 = new MyThread4_2(lock); my1.setName("A"); my2.setName("B"); my1.start(); my2.start(); } }

线程 B begin wait
线程 A begin wait
释放线程才会出现打印两个线程
将lock.wait() 改成Thread.sleep()就是同步的 效果。
(二)、线程notify不释放锁
package com.it.po.thread8; import java.sql.Time; public class Service2 { public void methodA(Object lock){ synchronized (lock){ try { System.out.println("线程 "+Thread.currentThread().getName()+" begin wait"); lock.wait(); System.out.println("线程 "+Thread.currentThread().getName()+" end wait"); } catch (InterruptedException e) { e.printStackTrace(); } } } public void methodB(Object lock){ synchronized (lock){ try { System.out.println("线程 "+Thread.currentThread().getName()+" begin notify"); System.out.println("begin time= "+System.currentTimeMillis()); lock.notify(); Thread.sleep(4000); System.out.println("end time= "+System.currentTimeMillis()); System.out.println("线程 "+Thread.currentThread().getName()+" end notify"); } catch (InterruptedException e) { e.printStackTrace(); } } } }
package com.it.po.thread8; public class MyThread5_1 extends Thread { private Object lock; public MyThread5_1(Object lock) { this.lock = lock; } @Override public void run() { super.run(); new Service2().methodA(lock); } }
package com.it.po.thread8; public class MyThread5_2 extends Thread { private Object lock; public MyThread5_2(Object lock) { this.lock = lock; } @Override public void run() { super.run(); new Service2().methodB(lock); } }
package com.it.po.thread8; public class Run6 { public static void main(String[] args) throws InterruptedException { Object lock = new Object(); MyThread5_1 my1 = new MyThread5_1(lock); MyThread5_2 my2 = new MyThread5_2(lock); my1.setName("A"); my2.setName("B"); my1.start(); Thread.sleep(100); my2.start(); } }
线程 A begin wait 线程 B begin notify begin time= 1574518908105 end time= 1574518912105 线程 B end notify 线程 A end wait
(三)当wait遇到interrupt方法
package com.it.po.thread8; public class Service1 { public void methodA(Object lock){ synchronized (lock){ try { System.out.println("线程 "+Thread.currentThread().getName()+" begin wait"); lock.wait(); System.out.println("线程 "+Thread.currentThread().getName()+" end wait"); } catch (InterruptedException e) { System.out.println("wait 遇到interrupt。。。"); e.printStackTrace(); } } } }
package com.it.po.thread8; public class MyThread6_1 extends Thread { private Object lock; public MyThread6_1(Object lock) { this.lock = lock; } @Override public void run() { super.run(); new Service1().methodA(lock); } }
package com.it.po.thread8; public class Run7 { public static void main(String[] args) throws InterruptedException { Object lock = new Object(); MyThread6_1 my1 = new MyThread6_1(lock); my1.setName("A"); my1.start(); Thread.sleep(2000); my1.interrupt(); } }
线程 A begin wait wait 遇到interrupt。。。 java.lang.InterruptedException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at com.it.po.thread8.Service1.methodA(Service1.java:9) at com.it.po.thread8.MyThread6_1.run(MyThread6_1.java:11)
总结:
1.执行同步代码块会释放锁
2.执行wait会释放锁。
3.执行notify不会释放锁
4.执行同步代码块时遇到异常会释放锁。
(四)、只通知一个线程
执行notify时,只是随机通知一个线程进行唤醒。
package com.it.po.thread9; public class Service1 { public void methodA(Object lock){ try { synchronized (lock) { System.out.println("线程 " + Thread.currentThread().getName() + " begin wait"); lock.wait(); System.out.println("线程 " + Thread.currentThread().getName() + " end wait"); } } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.it.po.thread9; public class MyThread1_1 extends Thread { private Object lock; public MyThread1_1(Object lock) { this.lock = lock; } @Override public void run() { super.run(); new Service1().methodA(lock); } }
package com.it.po.thread9; public class MyThread1_2 extends Thread { private Object lock; public MyThread1_2(Object lock) { this.lock = lock; } @Override public void run() { super.run(); new Service1().methodA(lock); } }
package com.it.po.thread9; public class MyThread1_3 extends Thread { private Object lock; public MyThread1_3(Object lock) { this.lock = lock; } @Override public void run() { super.run(); new Service1().methodA(lock); } }
package com.it.po.thread9; public class NotifyThread1_4 extends Thread { private Object lock; public NotifyThread1_4(Object lock) { this.lock = lock; } @Override public void run() { super.run(); synchronized (lock){ lock.notify(); } } }
package com.it.po.thread9; public class Run1 { public static void main(String[] args) throws InterruptedException { Object lock = new Object(); MyThread1_1 my1 = new MyThread1_1(lock); MyThread1_2 my2 = new MyThread1_2(lock); MyThread1_3 my3 = new MyThread1_3(lock); NotifyThread1_4 my4 = new NotifyThread1_4(lock); my1.setName("A"); my2.setName("B"); my3.setName("C"); my1.start(); my2.start(); my3.start(); Thread.sleep(2000); //保证先执行wait my4.setName("D"); my4.start(); } }
第一次执行
线程 B begin wait
线程 C begin wait
线程 A begin wait
线程 B end wait
第二次执行
线程 A begin wait
线程 C begin wait
线程 B begin wait
线程 A end wait
第三次执行
线程 C begin wait
线程 B begin wait
线程 A begin wait
线程 C end wait

修改成唤醒全部线程
package com.it.po.thread9; public class NotifyThread1_4 extends Thread { private Object lock; public NotifyThread1_4(Object lock) { this.lock = lock; } @Override public void run() { super.run(); synchronized (lock){ lock.notify(); lock.notify(); lock.notify(); } } }
线程 A begin wait
线程 C begin wait
线程 B begin wait
线程 A end wait
线程 B end wait
线程 C end wait
(五)、唤醒所有线程(上面的例子修改)
可以用notifyAll
package com.it.po.thread9; public class NotifyThread1_4 extends Thread { private Object lock; public NotifyThread1_4(Object lock) { this.lock = lock; } @Override public void run() { super.run(); synchronized (lock){ lock.notifyAll(); } } }
线程 A begin wait
线程 B begin wait
线程 C begin wait
线程 C end wait
线程 B end wait
线程 A end wait
(六)、方法wait(long)的使用
等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。
package com.it.po.thread9; import org.omg.CORBA.OBJ_ADAPTER; public class Run2 { static private Object lock=new Object(); static private Runnable runnable =new Runnable() { @Override public void run() { try { synchronized (lock) { System.out.println("线程 wait begin " + System.currentTimeMillis()); lock.wait(5000); System.out.println("线程 wait end " + System.currentTimeMillis()); } } catch (InterruptedException e) { e.printStackTrace(); } } }; public static void main(String[] args) throws InterruptedException { runnable.run(); } }
线程 wait begin 1574592435421 线程 wait end 1574592440422
在wait中获得通知
package com.it.po.thread9; import com.it.po.thread05.Task1; import org.omg.CORBA.OBJ_ADAPTER; public class Run2 { static private Object lock=new Object(); static private Runnable runnable =new Runnable() { @Override public void run() { try { synchronized (lock) { System.out.println("线程 wait begin " + System.currentTimeMillis()); lock.wait(5000); System.out.println("线程 wait end " + System.currentTimeMillis()); } } catch (InterruptedException e) { e.printStackTrace(); } } }; static private Runnable runnable2 =new Runnable() { @Override public void run() { synchronized (lock) { System.out.println("线程 notify begin " + System.currentTimeMillis()); lock.notify(); System.out.println("线程 notify end " + System.currentTimeMillis()); } } }; public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(runnable); t1.start(); Thread.sleep(2000); Thread t2 = new Thread(runnable2); t2.start(); } }
线程 wait begin 1574593179679 线程 notify begin 1574593181679 线程 notify end 1574593181679 线程 wait end 1574593181679
2s后被唤醒。
注意:如修改如下
package com.it.po.thread9; import com.it.po.thread05.Task1; import org.omg.CORBA.OBJ_ADAPTER; public class Run2 { static private Object lock=new Object(); static private Runnable runnable =new Runnable() { @Override public void run() { try { synchronized (lock) { System.out.println("线程 wait begin " + System.currentTimeMillis()); lock.wait(5000); System.out.println("线程 wait end " + System.currentTimeMillis()); } } catch (InterruptedException e) { e.printStackTrace(); } } }; static private Runnable runnable2 =new Runnable() { @Override public void run() { synchronized (lock) { System.out.println("线程 notify begin " + System.currentTimeMillis()); lock.notify(); System.out.println("线程 notify end " + System.currentTimeMillis()); } } }; public static void main(String[] args) throws InterruptedException { /* Thread t1 = new Thread(runnable); t1.start(); Thread.sleep(2000); Thread t2 = new Thread(runnable2); t2.start();*/ runnable.run(); Thread.sleep(2000); runnable2.run(); } }
这就一个线程mian执行
线程 wait begin 1574593273487 线程 wait end 1574593278488 线程 notify begin 1574593280488 线程 notify end 1574593280488
(七)、通知过早
package com.it.po.thread9; public class Run3 { static private Object lock=new Object(); static private Runnable runnable1 =new Runnable() { @Override public void run() { try { synchronized (lock) { System.out.println("线程1 wait begin " ); lock.wait(); System.out.println("线程1 wait end " ); } } catch (InterruptedException e) { e.printStackTrace(); } } }; static private Runnable runnable2 =new Runnable() { @Override public void run() { synchronized (lock) { System.out.println("线程 2 begin " ); lock.notify(); System.out.println("线程 2 end " ); } } }; public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(runnable1); t1.start(); // Thread.sleep(2000); Thread t2 = new Thread(runnable2); t2.start(); } }
可能出现先通知在wait

线程 2 begin 线程 2 end 线程1 wait begin
修改
package com.it.po.thread9; public class Run4 { private Object lock=new Object(); private Boolean isFirstRun=false; private Runnable runnable1 =new Runnable() { @Override public void run() { try { synchronized (lock) { while (isFirstRun==false) { System.out.println("线程1 wait begin "); lock.wait(); System.out.println("线程1 wait end "); } } } catch (InterruptedException e) { e.printStackTrace(); } } }; private Runnable runnable2 =new Runnable() { @Override public void run() { synchronized (lock) { System.out.println("线程 2 begin " ); lock.notify(); System.out.println("线程 2 end " ); isFirstRun=true; } } }; public static void main(String[] args) throws InterruptedException { Run4 run4 = new Run4(); Thread t1 = new Thread(run4.runnable1); t1.start(); Thread.sleep(2000); Thread t2 = new Thread(run4.runnable2); t2.start(); } }
线程1 wait begin 线程 2 begin 线程 2 end 线程1 wait end
while()循环一次
(八)、等待wait的条件发送变化
package com.it.po.thread9; public class Add { private String lock; public Add(String lock) { this.lock = lock; } public void add(){ synchronized (lock){ ValueObject.list.add("po"); lock.notifyAll(); } } }
package com.it.po.thread9; import java.util.ArrayList; import java.util.List; public class ValueObject { public static List<String> list=new ArrayList(); }
package com.it.po.thread9; public class Subtract { private String lock; public Subtract(String lock) { this.lock = lock; } public void subtract(){ try { synchronized (lock){ if(ValueObject.list.size()==0){ System.out.println("线程 "+Thread.currentThread().getName()+" begin wait"); lock.wait(); System.out.println("线程 "+Thread.currentThread().getName()+" end wait"); } ValueObject.list.remove(0); System.out.println("list size= "+ValueObject.list.size()); } } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.it.po.thread9; public class ThreadAdd extends Thread { private Add add; public ThreadAdd(Add add) { this.add = add; } @Override public void run() { super.run(); add.add(); } }
package com.it.po.thread9; public class SubtractThread extends Thread { private Subtract subtract; public SubtractThread(Subtract subtract) { this.subtract = subtract; } @Override public void run() { super.run(); subtract.subtract(); } }
package com.it.po.thread9; import com.it.po.thread03.ThreadA; public class Run5 { public static void main(String[] args) throws InterruptedException { String lock = new String("po"); Add add = new Add(lock); Subtract subtract = new Subtract(lock); SubtractThread s1 = new SubtractThread(subtract); s1.setName("A"); SubtractThread s2 = new SubtractThread(subtract); s2.setName("B"); //先删除两次 s1.start(); s2.start(); Thread.sleep(1000); ThreadAdd a1 = new ThreadAdd(add); a1.start(); } }
在main中两条 sleep()之前,两个SubtractThread 进入wait状态,
1s过后,执行a1.start(),唤醒两条线程,第一天正确删除,第二个则报错
线程 A begin wait 线程 B begin wait 线程 B end wait list size= 0 线程 A end wait Exception in thread "A" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at java.util.ArrayList.rangeCheck(ArrayList.java:653) at java.util.ArrayList.remove(ArrayList.java:492) at com.it.po.thread9.Subtract.subtract(Subtract.java:15) at com.it.po.thread9.SubtractThread.run(SubtractThread.java:10)
如果解决报错
package com.it.po.thread9; public class Subtract { private String lock; public Subtract(String lock) { this.lock = lock; } public void subtract(){ try { synchronized (lock){ while (ValueObject.list.size()==0){ System.out.println("线程 "+Thread.currentThread().getName()+" begin wait"); lock.wait(); System.out.println("线程 "+Thread.currentThread().getName()+" end wait"); } ValueObject.list.remove(0); System.out.println("list size= "+ValueObject.list.size()); } } catch (InterruptedException e) { e.printStackTrace(); } } }

线程 B begin wait 线程 A begin wait 线程 A end wait list size= 0 线程 B end wait 线程 B begin wait
分析:
1.注意其实线程s1和s2是同步的,只不过调用wait释放锁,才有异步的感觉
2.当执行 a1.start(); 添加一个元素再通知s1 和s2线程时,其中一个
线程发现ValueObject.list.size()=1,这个线程结束while成功删除元素,
另一个线程执行完while之后,发现 ValueObject.list.size()==0 又进入wait状态
浙公网安备 33010602011771号