java线程间通信之wait/notify实现

想一下,在没有等待/通知之前,如何实现线程间通信?

一般都是多个线程共享同一个变量,然后根据变量的变化决定相应操作。但是多线程获取共享变量值这个过程既耗时,又不能保证完全正确。

所以需要引入等待/通知机制。

方法wait()可以使当前执行代码的线程进入等待状态,wait()是object类的方法,在调用wait()前,线程必须获得该对象的对象级别锁,也就是只能在同步方法或同步方法块中执行该方法,否则会抛一个runtimeexception,IllegalMonitorStateException,运行时异常不需要try-cach

方法notify()可以使当前对象中某个正在等待的线程变为继续执行,它和wait()方法的使用条件类似。有一点要注意,那就是在执行notify()方法后,当前线程并不会立马释放锁,而是要等到同步方法或同步代码块执行完,它才会释放锁

 

在同步代码块中使用wait的总结:

1)同步代码块执行完,对象的锁就会自动释放。

2)同步代码块里出现异常导致线程终止,锁也会释放。

3)当线程调用wait呈等待状态时,调用此线程的interrupt方法,会报InterruptedException异常。

 

wait()还可以这样用wait(xxx).

 

当在使用wait/notify机制时,要注意不要提前notify,那样可能导致后面执行wait的线程永远不被唤醒。

实例生产者/消费者

 

最后来个示例,20个线程备份数据库,A-B-A-B。。。这样进行交叉备份,看代码

 1 public class DBtools {
 2 
 3     String flag = "A";
 4     
 5     synchronized public void backupA(){
 6         try {
 7             while (flag.equals("B")) {
 8                 wait();
 9             }
10             System.out.println("备份数据到A库");
11             Thread.sleep(1000);
12             flag = "B";
13             notifyAll();
14         } catch (InterruptedException e) {
15             e.printStackTrace();
16         }
17     }
18     synchronized public void backupB(){
19         try {
20             while (flag.equals("A")) {
21                 wait();
22             }
23             System.out.println("备份数据到B库");
24             Thread.sleep(1000);
25             flag = "A";
26             notifyAll();
27         } catch (InterruptedException e) {
28             e.printStackTrace();
29         }
30     }
31 }
 1 public class BackupA extends Thread {
 2     private DBtools dBtools;
 3     public BackupA(DBtools dBtools) {
 4         this.dBtools = dBtools;
 5     }
 6     @Override
 7     public void run() {
 8         dBtools.backupA();
 9     }
10 }
 1 public class BackupB extends Thread {
 2     private DBtools dBtools;
 3     public BackupB(DBtools dBtools) {
 4         this.dBtools = dBtools;
 5     }
 6     @Override
 7     public void run() {
 8         dBtools.backupB();
 9     }
10 }
 1 public class Run {
 2     public static void main(String[] args) {
 3         DBtools dBtools = new DBtools();
 4         for (int i = 0; i < 10; i++) {
 5             BackupA backupA = new BackupA(dBtools);
 6             BackupB backupB = new BackupB(dBtools);
 7             backupA.start();
 8             backupB.start();
 9         }
10     }
11 }

 

posted @ 2017-04-04 11:49  夏威夷8080  阅读(428)  评论(0编辑  收藏  举报