wait方法是Object中的方法,这个方法的功能特性:
1).执行wait方法的前提是当前线程已经获取到对象的锁,也就是wait方法必须在synchronized修饰的代码块或者方法中使用。
2).执行wait以后,会失去锁的全部权
3).wait方法执行后会一直等待,直到被调用notify()、notifyAll()或者所在线程被中断。
4).被调用notify()或者notifyAll()后,线程仍是会等待,直到拥有锁的全部权,才会继续往下执行。
下面举个例子:java
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); Thread t2 = new Thread(new Test().new Tt2(lock1)); t1.start(); Thread.sleep(1000); t2.start(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { try { System.out.println(this.getClass()+"-------1"); synchronized (lock1) { Thread.sleep(2000); System.out.println("waiting start"); lock1.wait(); } System.out.println("waiting end"); } catch (InterruptedException e) { e.printStackTrace(); } } } class Tt2 implements Runnable{ private Object lock1; public Tt2(Object lock1) { this.lock1 = lock1; } @Override public void run() { System.out.println(this.getClass()+"-------1"); synchronized (lock1) { try { System.out.println(this.getClass()+"-------2"); lock1.notify(); Thread.sleep(1000); System.out.println(this.getClass()+"-------3"); } catch (Exception e) { e.printStackTrace(); } } } }
执行结果:多线程
class Test$Tt1-------1 class Test$Tt2-------1 waiting start class Test$Tt2-------2 class Test$Tt2-------3 waiting end
分析一下:
第一、2行:t1和t2启动,t1先获取到锁因此t2一直被阻塞住
第三、4行:t1中执行了wait,锁被释放,因此t2继续执行下去。
第五、6行:t2中调用了notify()可是t1没有立刻执行,由于锁如今是被t2拥有,等t2执行完成释放锁后,t1继续执行。ide
notify已经在上面有提到过,notify和notifyAll 的做用是唤醒正在wait的线程,notify是随机唤醒wait线程中的一个,notifyAll 则是唤醒所有。this
1).执行notify、notifyAll 方法的前提是当前线程已经获取到对象的锁,也就是必须在synchronized修饰的代码块或者方法中使用。这个和wait是同样的。
2).被调用notify()或者notifyAll()后,线程仍是会等待,直到拥有锁的全部权,才会继续往下执行。
3)notify、notifyAll不会释放锁,这个与wait不一样。线程
在多线程的操做中,锁的释放与否是必需要清楚的,wait是会释放锁,而notify(notifyAll)则不会。先举个wait的例子:code
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); Thread t2 = new Thread(new Test().new Tt2(lock1)); t1.start(); Thread.sleep(100); t2.start(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { try { synchronized (lock1) { System.out.println(Thread.currentThread().getName()+"---start"); lock1.wait(); Thread.sleep(3000); System.out.println(Thread.currentThread().getName()+"---end"); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Tt2 implements Runnable{ private Object lock1; public Tt2(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } }
执行结果:对象
Thread-0---start Thread-1---start Thread-1---end
Thread-0执行wait后立刻释放了锁,因此Thread-1很快接着就执行。get
再来notify的例子,其实就是把上一个例子wait()改为nofity():it
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); Thread t2 = new Thread(new Test().new Tt2(lock1)); t1.start(); Thread.sleep(100); t2.start(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { try { synchronized (lock1) { System.out.println(Thread.currentThread().getName()+"---start"); lock1.notify(); Thread.sleep(3000); System.out.println(Thread.currentThread().getName()+"---end"); } } catch (InterruptedException e) { e.printStackTrace(); } } } class Tt2 implements Runnable{ private Object lock1; public Tt2(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } }
执行结果:io
Thread-0---start Thread-0---end Thread-1---start Thread-1---end
可见Thread-0在执行nofity后并无释放锁,而是等待代码块执行完以后才释放锁,Thread-1才能继续执行。
不管是notify仍是wait都是要先获取锁,既必须在synchronized内使用,举个反例:
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); t1.run(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { try { lock1.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } }
执行结果:
Exception in thread "main" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:502) at Test$Tt1.run(Test.java:24) at java.lang.Thread.run(Thread.java:748) at Test.main(Test.java:11)
以前说道interrupt(),并不会直接中断线程,而是会给线程一个中断标志,并且包括sleep、wait、join会抛出InterruptedException。
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); t1.start(); Thread.sleep(100); t1.interrupt(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); lock1.wait(); System.out.println(Thread.currentThread().getName()+"---end"); }catch (InterruptedException e) { System.out.println("线程被中断了");; } catch (Exception e) { e.printStackTrace(); } } } }
执行结果:
Thread-0---start 线程被中断了
notifyAll和nofity惟一的不一样就是,能够唤醒所有和唤醒一个, 先举个nofity的例子
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); Thread t2 = new Thread(new Test().new Tt1(lock1)); Thread t3 = new Thread(new Test().new Tt2(lock1)); t1.start(); Thread.sleep(100); t2.start(); Thread.sleep(100); t3.start(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---wait"); lock1.wait(); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } } class Tt2 implements Runnable{ private Object lock1; public Tt2(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---notify"); lock1.notify(); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } }
执行结果:
Thread-0---start Thread-0---wait Thread-1---start Thread-1---wait Thread-2---start Thread-2---notify Thread-2---end Thread-0---end
Thread-0和Thread-1在wait,Thread-2执行了notify,但只有Thread-0被唤醒,从新开始执行,Thread-1还在wait。
再来看看nofityAll:
public static void main(String[] args) throws InterruptedException { Object lock1 = new Object(); Thread t1 = new Thread(new Test().new Tt1(lock1)); Thread t2 = new Thread(new Test().new Tt1(lock1)); Thread t3 = new Thread(new Test().new Tt2(lock1)); t1.start(); Thread.sleep(100); t2.start(); Thread.sleep(100); t3.start(); } class Tt1 implements Runnable{ private Object lock1; public Tt1(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---wait"); lock1.wait(); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } } class Tt2 implements Runnable{ private Object lock1; public Tt2(Object lock1) { this.lock1 = lock1; } @Override public void run() { synchronized (lock1) { try { System.out.println(Thread.currentThread().getName()+"---start"); System.out.println(Thread.currentThread().getName()+"---notifyAll"); lock1.notifyAll(); System.out.println(Thread.currentThread().getName()+"---end"); } catch (Exception e) { e.printStackTrace(); } } } }
执行结果:
Thread-0---start Thread-0---wait Thread-1---start Thread-1---wait Thread-2---start Thread-2---notifyAll Thread-2---end Thread-1---end Thread-0---end
Thread-2执行了notifyAll后,Thread-1和Thread-0都被唤醒。