Java线程:线程交互
一、基础知识
java.lang.Object的类的三个方法:
void notify():唤醒在此对象监视器上等待的单个线程。
void notifyAll():唤醒在此对象监视器上等待的所有线程。
void wait():导致当前线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法。
void wait(long timeout):导致当前线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者是超过指定时间。
void wait(long timeout,int nanos):导致当前线程等待,直到其他线程调用此对象的notify()方法或notifyAll()方法,或者是其他某个线程中断当前线程,或超过某个实际时间。
以上方法使用要点:
必须从同步环境中调用这些方法。线程不能调用对象上等待或通知的方法,除非它拥有那个对象的锁。
以上几种方法都是Object的实例方法,与每个对象具有锁是一样的,每个对象可以有一个线程列表,它们等待来自该信号。线程通过wait()获得这个等待列表。它不再执行任何其他指令,直到调用notify()为止。如果多个线程在同一个对象上等待,则将只选择一个线程继续执行。如果没有线程等待,则不采取操作。如;
1 package Thread; 2 3 public class Test2 { 4 public static void main(String[] args){ 5 ThreadB b=new ThreadB(); 6 b.start();//线程A拥有b对象上的锁。线程为了调用wait()或notify()方法,该线程必须是那个对象锁的拥有者 7 synchronized(b){ 8 try{ 9 System.out.println("等待对象b完成计算...>"); 10 b.wait();//当前线程A等待 11 }catch(InterruptedException e){ 12 e.printStackTrace(); 13 } 14 System.out.println("b对象计算完毕,其总和是:"+b.total); 15 } 16 } 17 } 18 class ThreadB extends Thread{ 19 int total; 20 public void run(){ 21 synchronized(this){ 22 for(int i=0;i<101;i++){ 23 total+=i; 24 } 25 notify();//(完成计算)唤醒在此对象监视器上等待的单个线程,在本例中A被唤醒。 26 } 27 } 28 }
1 等待对象b完成计算...> 2 b对象计算完毕,其总和是:5050
在对象上调用wait()方法时,执行该代码的线程立刻放弃它在该对象的锁,然后调用调用notify()方法,如果线程仍然在完成同步代码,则线程移出之前不会放弃锁。因此,只要调用notify()并不意味着这时的锁变得可用。
二、多个线程在等待一个对象锁时使用notifyAll()
多数情况下,最好通知等待某个对象的所有线程。如果这样做,可以在对象上使用notifyAll()方法,让所有等待的线程返回到可运行状态。如:
1 package Thread; 2 3 public class Test2 extends Thread{ 4 public static void main(String[] args){ 5 Calculator calculator=new Calculator(); 6 new Test2(calculator).start(); 7 new Test2(calculator).start(); 8 new Test2(calculator).start(); 9 calculator.start();//线程A拥有b对象上的锁。线程为了调用wait()或notify()方法,该线程必须是那个对象锁的拥有者 10 } 11 Calculator calculator; 12 public Test2(Calculator calculator){ 13 this.calculator=calculator; 14 } 15 public void run(){ 16 synchronized(calculator){ 17 try{ 18 System.out.println(Thread.currentThread()+"等待计算结果...>"); 19 calculator.wait();//当前线程A等待 20 }catch(InterruptedException e){ 21 e.printStackTrace(); 22 } 23 System.out.println(Thread.currentThread()+"结果为:"+calculator.total); 24 } 25 } 26 } 27 class Calculator extends Thread{ 28 int total; 29 public void run(){ 30 synchronized(this){ 31 for(int i=0;i<101;i++){ 32 total+=i; 33 } 34 notifyAll();//(完成计算)唤醒在此对象监视器上等待的单个线程,在本例中A被唤醒。 35 } 36 } 37 }
1 Thread[Thread-1,5,main]等待计算结果...> 2 Thread[Thread-3,5,main]等待计算结果...> 3 Thread[Thread-2,5,main]等待计算结果...> 4 Thread[Thread-2,5,main]结果为:5050 5 Thread[Thread-3,5,main]结果为:5050 6 Thread[Thread-1,5,main]结果为:5050