wait、notify和notifyAll
首先,这些方法属于Object,而不属于Thread。其次,obj.wait()、obj.notify()必须要与synchronized(obj)一起使用,也就是说obj.wait()、obj.notify()必须存在于synchronized(obj){…}的代码块内,负责就会抛出java.lang.IllegalMonitorStateException异常。一下是对这几种方法的简要介绍:
1.如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态(wait()与sleep()区别:wait()释放了锁,sleep()没有)。
2.如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。
3.如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
注:wait()有3种调用方式:wait()、wait(long timeout)、wait(long timeout, int nanos)
public class ThreadTest { public static void main(String[] args) { final PrintClass pc = new PrintClass(); Thread t1 = new Thread(new Runnable() { @Override public void run() { pc.ptintText("Thread-1"); } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { pc.ptintText("Thread-2"); } }); t1.start(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } } class PrintClass { public void ptintText(String text) { synchronized (this) { for (int i = 0; i < 15; i++) { try { System.out.println(text + ",count" + i); if ("Thread-1".equals(text) && i == 5) { this.wait(); } if ("Thread-2".equals(text) && i == 9) { this.notify(); this.wait(); } if ("Thread-1".equals(text) && i == 14) { this.notify(); } Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } }
线程1从0数到5交给线程2,线程2从0数到9再交给线程1,线程1从6数到14再交给线程2,线程2从10数到14,结束。
具体过程是:当线程1数到5时,调用wait()释放了当前的锁,交给了线程2并自己等待。当线程2数到9时,调用notify()激活了某一个等待的线程(这里等待的线程只有线程1,所以只能激活他),并且自己释放了锁,交给另一个线程(只能交给线程1,因为只有他)。然后线程1接着数到14,交给线程2,线程2数完。
在synchronized也可以使用这些方法:
class PrintClass { public synchronized void ptintText(String text) { for (int i = 0; i < 15; i++) { try { System.out.println(text + ",count" + i); if ("Thread-1".equals(text) && i == 5) { wait(); } if ("Thread-2".equals(text) && i == 9) { notify(); wait(); } if ("Thread-1".equals(text) && i == 14) { notify(); } Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
将打印类改成这样,与前面的demo效果相同,也是用this这个类实例来同步的。
好文章!666,学习了