java中线程通信(传统的线程通信)

假设现在系统有两个线程,这两个线程分别代表存款者和取钱者——现在假设系统有一种特殊的要求,系统要求存款者和取钱者不断地重复存款、取钱的动作。而且要求每当存款者将钱存入指定账户后,取钱者就立即取出该笔钱。不允许存款者连续两次存钱,也不允许取钱者连续两次取钱。

为了实现这种功能,可以借助Object类提供的wait()、notify()、notifyAll() 3 个方法,这3个方法并不属于Thread类,而是属于Object类。但这3 个方法必须由同步监视器对象来调用,这可分以下两种情况:

1、对于使用synchronized修饰的同步方法,因为该类的默认实例是(this)就是同步监视器。所以可以在同步方法中直接调用这3个方法。

2、对于使用synchronized修饰的同步代码块,同步监视器是synchronized后括号里的对象,所以必须使用该对象调用这3个方法。

关于这3个方法的解释如下:

wait():导致当前线程等待,直到其他线程调用该同步监视器的notify()方法或notifyAll()方法来唤醒该线程。该wait()方法有三种形式——无时间参数的wait(一直等待,知道其他线程通知),带毫秒参数的wait和带毫秒、毫微妙参数的wait(这两种方法都是等待指定时间后自动苏醒) 调用wait方法的当前线程会释放对该同步监视器的锁定。

notify():唤醒在次同步监视器上等待的单个线程。如果所有的线程都在此同步监视器上等待,则会选择唤醒其中一个线程。选择是任意的。只有当前线程放弃对该同步监视器的锁定后(使用wait方法),才可以执行被唤醒的线程。

notifyAll():唤醒在此同步监视器上等待的所有线程。只有当前线程放弃对同步监视器的锁定后,才可以执行被唤醒的线程。

 1 public class DrawTest{
 2     public static void main(String[] args){
 3         Account a=new Account("刘腾",10000);
 4         new DrawThread(a,100).start();
 5         new InThread(a,50).start();
 6         new InThread(a,60).start();
 7         new InThread(a,70).start();
 8     }
 9 }
10 //账户类
11 class Account{
12     private String name;
13     private double money;
14     private boolean flag=false;
15     
16     public Account(){}
17     public Account(String name,double money){
18         this.name=name;
19         this.money=money;
20     }
21     public double getMoney(){
22         return money;
23     }
24     public synchronized void draw(double drawmoney){
25             try{
26             //如果flag为假,说明还没有人往里面存钱,所以让该线程等待。
27                 if(!flag){
28                     wait();
29                 }else{
30                     System.out.println("取出钱数为:"+drawmoney+" 剩余钱数:"+(getMoney()-drawmoney));
31                     flag=false;
32                     notifyAll();
33                 }
34             }catch(Exception e){System.out.println(e);}
35         }
36     public synchronized void deposit(double inmoney){
37         try{
38             if(!flag){
39                 System.out.println("存入钱数为:"+inmoney+" 目前的钱数为:"+(getMoney()+inmoney));
40                 flag=true;
41                 notifyAll();
42             }else{
43                 wait();
44             }
45         }catch(Exception e){}
46     } 
47 }
48 //取钱线程
49 class DrawThread extends Thread{
50     private Account account;
51     private double drawmoney;
52     
53     public DrawThread (Account account,double drawmoney){
54         this.account=account;
55         this.drawmoney=drawmoney;
56     }
57     public void run(){
58         for(int i=0;i<100;i++){
59             account.draw(drawmoney);
60         }
61     }
62 }
63 class InThread extends Thread{
64     private Account account;
65     private double inmoney;
66     
67     public InThread(Account account,double inmoney){
68         this.account=account;
69         this.inmoney=inmoney;
70     }
71     public void run(){
72         for(int k=0;k<100;k++){
73             account.deposit(inmoney);
74         }
75     }
76 }
原文地址:https://www.cnblogs.com/teng-IT/p/4451670.html