Java多线程编程总结--新特征-条件变量

 

件变量是Java5线程中很重要的一个概念,顾名思义,条件变量就是表示条件的一种变量。但是必须说明,这里的条件是没有实际含义的,仅仅是个标记而已,并且条件的含义往往通过代码来赋予其含义。
 
这里的条件和普通意义上的条件表达式有着天壤之别。
 
条件变量都实现了java.util.concurrent.locks.Condition接口,条件变量的实例化是通过一个Lock对象上调用newCondition()方法来获取的,这样,条件就和一个锁对象绑定起来了。因此,Java中的条件变量只能和锁配合使用,来控制并发程序访问竞争资源的安全。
 
条件变量的出现是为了更精细控制线程等待与唤醒,在Java5之前,线程的等待与唤醒依靠的是Object对象的wait()和notify()/notifyAll()方法,这样的处理不够精细。
 
而在Java5中,一个锁可以有多个条件,每个条件上可以有多个线程等待,通过调用await()方法,可以让线程在该条件下等待。当调用signalAll()方法,又可以唤醒该条件下的等待的线程。有关Condition接口的API可以具体参考JavaAPI文档。
 
条件变量比较抽象,原因是他不是自然语言中的条件概念,而是程序控制的一种手段。
 
下面以一个银行存取款的模拟程序为例来揭盖Java多线程条件变量的神秘面纱:
 
有一个账户,多个用户(线程)在同时操作这个账户,有的存款有的取款,存款随便存,取款有限制,不能透支,任何试图透支的操作都将等待里面有足够存款才执行操作。
Java代码 复制代码
  1. import  java.util.concurrent.ExecutorService;    
  2. import  java.util.concurrent.Executors;    
  3. import  java.util.concurrent.locks.Condition;    
  4. import  java.util.concurrent.locks.Lock;    
  5. import  java.util.concurrent.locks.ReentrantLock;    
  6.   
  7. /**   
  8. * Java线程:条件变量   
  9.  
  10. * @author leizhimin 2009-11-5 10:57:29   
  11. */     
  12. public   class  Test {    
  13.          public   static   void  main(String[] args) {    
  14.                  //创建并发访问的账户    
  15.                 MyCount myCount =  new  MyCount( "95599200901215522"10000 );    
  16.                  //创建一个线程池    
  17.                 ExecutorService pool = Executors.newFixedThreadPool( 2 );    
  18.                 Thread t1 =  new  SaveThread( "张三" , myCount,  2000 );    
  19.                 Thread t2 =  new  SaveThread( "李四" , myCount,  3600 );    
  20.                 Thread t3 =  new  DrawThread( "王五" , myCount,  2700 );    
  21.                 Thread t4 =  new  SaveThread( "老张" , myCount,  600 );    
  22.                 Thread t5 =  new  DrawThread( "老牛" , myCount,  1300 );    
  23.                 Thread t6 =  new  DrawThread( "胖子" , myCount,  800 );    
  24.                  //执行各个线程    
  25.                 pool.execute(t1);    
  26.                 pool.execute(t2);    
  27.                 pool.execute(t3);    
  28.                 pool.execute(t4);    
  29.                 pool.execute(t5);    
  30.                 pool.execute(t6);    
  31.                  //关闭线程池    
  32.                 pool.shutdown();    
  33.         }    
  34. }    
  35.   
  36. /**   
  37. * 存款线程类   
  38. */     
  39. class  SaveThread  extends  Thread {    
  40.          private  String name;                 //操作人    
  41.          private  MyCount myCount;         //账户    
  42.          private   int  x;                             //存款金额    
  43.   
  44.         SaveThread(String name, MyCount myCount,  int  x) {    
  45.                  this .name = name;    
  46.                  this .myCount = myCount;    
  47.                  this .x = x;    
  48.         }    
  49.   
  50.          public   void  run() {    
  51.                 myCount.saving(x, name);    
  52.         }    
  53. }    
  54.   
  55. /**   
  56. * 取款线程类   
  57. */     
  58. class  DrawThread  extends  Thread {    
  59.          private  String name;                 //操作人    
  60.          private  MyCount myCount;         //账户    
  61.          private   int  x;                             //存款金额    
  62.   
  63.         DrawThread(String name, MyCount myCount,  int  x) {    
  64.                  this .name = name;    
  65.                  this .myCount = myCount;    
  66.                  this .x = x;    
  67.         }    
  68.   
  69.          public   void  run() {    
  70.                 myCount.drawing(x, name);    
  71.         }    
  72. }    
  73.   
  74.   
  75. /**   
  76. * 普通银行账户,不可透支   
  77. */     
  78. class  MyCount {    
  79.          private  String oid;                          //账号    
  80.          private   int  cash;                              //账户余额    
  81.          private  Lock lock =  new  ReentrantLock();                 //账户锁    
  82.          private  Condition _save = lock.newCondition();     //存款条件    
  83.          private  Condition _draw = lock.newCondition();     //取款条件    
  84.   
  85.         MyCount(String oid,  int  cash) {    
  86.                  this .oid = oid;    
  87.                  this .cash = cash;    
  88.         }    
  89.   
  90.          /**   
  91.          * 存款   
  92.          *   
  93.          * @param x        操作金额   
  94.          * @param name 操作人   
  95.          */     
  96.          public   void  saving( int  x, String name) {    
  97.                 lock.lock();                         //获取锁    
  98.                  if  (x >  0 ) {    
  99.                         cash += x;                     //存款    
  100.                         System.out.println(name +  "存款"  + x +  ",当前余额为"  + cash);    
  101.                 }    
  102.                 _draw.signalAll();             //唤醒所有等待线程。    
  103.                 lock.unlock();                     //释放锁    
  104.         }    
  105.   
  106.          /**   
  107.          * 取款   
  108.          *   
  109.          * @param x        操作金额   
  110.          * @param name 操作人   
  111.          */     
  112.          public   void  drawing( int  x, String name) {    
  113.                 lock.lock();                                  //获取锁    
  114.                  try  {    
  115.                          if  (cash - x <  0 ) {    
  116.                                 _draw.await();              //阻塞取款操作    
  117.                         }  else  {    
  118.                                 cash -= x;                      //取款    
  119.                                 System.out.println(name +  "取款"  + x +  ",当前余额为"  + cash);    
  120.                         }    
  121.                         _save.signalAll();              //唤醒所有存款操作    
  122.                 }  catch  (InterruptedException e) {    
  123.                         e.printStackTrace();    
  124.                 }  finally  {    
  125.                         lock.unlock();                      //释放锁    
  126.                 }    
  127.         }    
  128. }  
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.locks.Condition; 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

/** 
* Java线程:条件变量 
* 
* @author leizhimin 2009-11-5 10:57:29 
*/ 
public class Test { 
        public static void main(String[] args) { 
                //创建并发访问的账户 
                MyCount myCount = new MyCount("95599200901215522", 10000); 
                //创建一个线程池 
                ExecutorService pool = Executors.newFixedThreadPool(2); 
                Thread t1 = new SaveThread("张三", myCount, 2000); 
                Thread t2 = new SaveThread("李四", myCount, 3600); 
                Thread t3 = new DrawThread("王五", myCount, 2700); 
                Thread t4 = new SaveThread("老张", myCount, 600); 
                Thread t5 = new DrawThread("老牛", myCount, 1300); 
                Thread t6 = new DrawThread("胖子", myCount, 800); 
                //执行各个线程 
                pool.execute(t1); 
                pool.execute(t2); 
                pool.execute(t3); 
                pool.execute(t4); 
                pool.execute(t5); 
                pool.execute(t6); 
                //关闭线程池 
                pool.shutdown(); 
        } 
} 

/** 
* 存款线程类 
*/ 
class SaveThread extends Thread { 
        private String name;                //操作人 
        private MyCount myCount;        //账户 
        private int x;                            //存款金额 

        SaveThread(String name, MyCount myCount, int x) { 
                this.name = name; 
                this.myCount = myCount; 
                this.x = x; 
        } 

        public void run() { 
                myCount.saving(x, name); 
        } 
} 

/** 
* 取款线程类 
*/ 
class DrawThread extends Thread { 
        private String name;                //操作人 
        private MyCount myCount;        //账户 
        private int x;                            //存款金额 

        DrawThread(String name, MyCount myCount, int x) { 
                this.name = name; 
                this.myCount = myCount; 
                this.x = x; 
        } 

        public void run() { 
                myCount.drawing(x, name); 
        } 
} 


/** 
* 普通银行账户,不可透支 
*/ 
class MyCount { 
        private String oid;                         //账号 
        private int cash;                             //账户余额 
        private Lock lock = new ReentrantLock();                //账户锁 
        private Condition _save = lock.newCondition();    //存款条件 
        private Condition _draw = lock.newCondition();    //取款条件 

        MyCount(String oid, int cash) { 
                this.oid = oid; 
                this.cash = cash; 
        } 

        /** 
         * 存款 
         * 
         * @param x        操作金额 
         * @param name 操作人 
         */ 
        public void saving(int x, String name) { 
                lock.lock();                        //获取锁 
                if (x > 0) { 
                        cash += x;                    //存款 
                        System.out.println(name + "存款" + x + ",当前余额为" + cash); 
                } 
                _draw.signalAll();            //唤醒所有等待线程。 
                lock.unlock();                    //释放锁 
        } 

        /** 
         * 取款 
         * 
         * @param x        操作金额 
         * @param name 操作人 
         */ 
        public void drawing(int x, String name) { 
                lock.lock();                                 //获取锁 
                try { 
                        if (cash - x < 0) { 
                                _draw.await();             //阻塞取款操作 
                        } else { 
                                cash -= x;                     //取款 
                                System.out.println(name + "取款" + x + ",当前余额为" + cash); 
                        } 
                        _save.signalAll();             //唤醒所有存款操作 
                } catch (InterruptedException e) { 
                        e.printStackTrace(); 
                } finally { 
                        lock.unlock();                     //释放锁 
                } 
        } 
}
 
Java代码 复制代码
  1. 李四存款 3600 ,当前余额为 13600     
  2. 张三存款 2000 ,当前余额为 15600     
  3. 老张存款 600 ,当前余额为 16200     
  4. 老牛取款 1300 ,当前余额为 14900     
  5. 胖子取款 800 ,当前余额为 14100     
  6. 王五取款 2700 ,当前余额为 11400     
  7.   
  8. Process finished with exit code  0   
李四存款3600,当前余额为13600 
张三存款2000,当前余额为15600 
老张存款600,当前余额为16200 
老牛取款1300,当前余额为14900 
胖子取款800,当前余额为14100 
王五取款2700,当前余额为11400 

Process finished with exit code 0
 假如我们不用锁和条件变量,如何实现此功能呢?下面是实现代码:
Java代码 复制代码
  1. import  java.util.concurrent.ExecutorService;    
  2. import  java.util.concurrent.Executors;    
  3.   
  4. /**   
  5. * Java线程:不用条件变量   
  6.  
  7. * @author leizhimin 2009-11-5 10:57:29   
  8. */     
  9. public   class  Test {    
  10.          public   static   void  main(String[] args) {    
  11.                  //创建并发访问的账户    
  12.                 MyCount myCount =  new  MyCount( "95599200901215522"10000 );    
  13.                  //创建一个线程池    
  14.                 ExecutorService pool = Executors.newFixedThreadPool( 2 );    
  15.                 Thread t1 =  new  SaveThread( "张三" , myCount,  2000 );    
  16.                 Thread t2 =  new  SaveThread( "李四" , myCount,  3600 );    
  17.                 Thread t3 =  new  DrawThread( "王五" , myCount,  2700 );    
  18.                 Thread t4 =  new  SaveThread( "老张" , myCount,  600 );    
  19.                 Thread t5 =  new  DrawThread( "老牛" , myCount,  1300 );    
  20.                 Thread t6 =  new  DrawThread( "胖子" , myCount,  800 );    
  21.                  //执行各个线程    
  22.                 pool.execute(t1);    
  23.                 pool.execute(t2);    
  24.                 pool.execute(t3);    
  25.                 pool.execute(t4);    
  26.                 pool.execute(t5);    
  27.                 pool.execute(t6);    
  28.                  //关闭线程池    
  29.                 pool.shutdown();    
  30.         }    
  31. }    
  32.   
  33. /**   
  34. * 存款线程类   
  35. */     
  36. class  SaveThread  extends  Thread {    
  37.          private  String name;                 //操作人    
  38.          private  MyCount myCount;         //账户    
  39.          private   int  x;                             //存款金额    
  40.   
  41.         SaveThread(String name, MyCount myCount,  int  x) {    
  42.                  this .name = name;    
  43.                  this .myCount = myCount;    
  44.                  this .x = x;    
  45.         }    
  46.   
  47.          public   void  run() {    
  48.                 myCount.saving(x, name);    
  49.         }    
  50. }    
  51.   
  52. /**   
  53. * 取款线程类   
  54. */     
  55. class  DrawThread  extends  Thread {    
  56.          private  String name;                 //操作人    
  57.          private  MyCount myCount;         //账户    
  58.          private   int  x;                             //存款金额    
  59.   
  60.         DrawThread(String name, MyCount myCount,  int  x) {    
  61.                  this .name = name;    
  62.                  this .myCount = myCount;    
  63.                  this .x = x;    
  64.         }    
  65.   
  66.          public   void  run() {    
  67.                 myCount.drawing(x, name);    
  68.         }    
  69. }    
  70.   
  71.   
  72. /**   
  73. * 普通银行账户,不可透支   
  74. */     
  75. class  MyCount {    
  76.          private  String oid;                          //账号    
  77.          private   int  cash;                              //账户余额    
  78.   
  79.         MyCount(String oid,  int  cash) {    
  80.                  this .oid = oid;    
  81.                  this .cash = cash;    
  82.         }    
  83.   
  84.          /**   
  85.          * 存款   
  86.          *   
  87.          * @param x        操作金额   
  88.          * @param name 操作人   
  89.          */     
  90.          public   synchronized   void  saving( int  x, String name) {    
  91.                  if  (x >  0 ) {    
  92.                         cash += x;                     //存款    
  93.                         System.out.println(name +  "存款"  + x +  ",当前余额为"  + cash);    
  94.                 }    
  95.                 notifyAll();             //唤醒所有等待线程。    
  96.         }    
  97.   
  98.          /**   
  99.          * 取款   
  100.          *   
  101.          * @param x        操作金额   
  102.          * @param name 操作人   
  103.          */     
  104.          public   synchronized   void  drawing( int  x, String name) {    
  105.                  if  (cash - x <  0 ) {    
  106.                          try  {    
  107.                                 wait();    
  108.                         }  catch  (InterruptedException e1) {    
  109.                                 e1.printStackTrace();    
  110.                         }    
  111.                 }  else  {    
  112.                         cash -= x;                      //取款    
  113.                         System.out.println(name +  "取款"  + x +  ",当前余额为"  + cash);    
  114.                 }    
  115.                 notifyAll();              //唤醒所有存款操作    
  116.         }    
  117. }  
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

/** 
* Java线程:不用条件变量 
* 
* @author leizhimin 2009-11-5 10:57:29 
*/ 
public class Test { 
        public static void main(String[] args) { 
                //创建并发访问的账户 
                MyCount myCount = new MyCount("95599200901215522", 10000); 
                //创建一个线程池 
                ExecutorService pool = Executors.newFixedThreadPool(2); 
                Thread t1 = new SaveThread("张三", myCount, 2000); 
                Thread t2 = new SaveThread("李四", myCount, 3600); 
                Thread t3 = new DrawThread("王五", myCount, 2700); 
                Thread t4 = new SaveThread("老张", myCount, 600); 
                Thread t5 = new DrawThread("老牛", myCount, 1300); 
                Thread t6 = new DrawThread("胖子", myCount, 800); 
                //执行各个线程 
                pool.execute(t1); 
                pool.execute(t2); 
                pool.execute(t3); 
                pool.execute(t4); 
                pool.execute(t5); 
                pool.execute(t6); 
                //关闭线程池 
                pool.shutdown(); 
        } 
} 

/** 
* 存款线程类 
*/ 
class SaveThread extends Thread { 
        private String name;                //操作人 
        private MyCount myCount;        //账户 
        private int x;                            //存款金额 

        SaveThread(String name, MyCount myCount, int x) { 
                this.name = name; 
                this.myCount = myCount; 
                this.x = x; 
        } 

        public void run() { 
                myCount.saving(x, name); 
        } 
} 

/** 
* 取款线程类 
*/ 
class DrawThread extends Thread { 
        private String name;                //操作人 
        private MyCount myCount;        //账户 
        private int x;                            //存款金额 

        DrawThread(String name, MyCount myCount, int x) { 
                this.name = name; 
                this.myCount = myCount; 
                this.x = x; 
        } 

        public void run() { 
                myCount.drawing(x, name); 
        } 
} 


/** 
* 普通银行账户,不可透支 
*/ 
class MyCount { 
        private String oid;                         //账号 
        private int cash;                             //账户余额 

        MyCount(String oid, int cash) { 
                this.oid = oid; 
                this.cash = cash; 
        } 

        /** 
         * 存款 
         * 
         * @param x        操作金额 
         * @param name 操作人 
         */ 
        public synchronized void saving(int x, String name) { 
                if (x > 0) { 
                        cash += x;                    //存款 
                        System.out.println(name + "存款" + x + ",当前余额为" + cash); 
                } 
                notifyAll();            //唤醒所有等待线程。 
        } 

        /** 
         * 取款 
         * 
         * @param x        操作金额 
         * @param name 操作人 
         */ 
        public synchronized void drawing(int x, String name) { 
                if (cash - x < 0) { 
                        try { 
                                wait(); 
                        } catch (InterruptedException e1) { 
                                e1.printStackTrace(); 
                        } 
                } else { 
                        cash -= x;                     //取款 
                        System.out.println(name + "取款" + x + ",当前余额为" + cash); 
                } 
                notifyAll();             //唤醒所有存款操作 
        } 
}
 
输出结果为:
Java代码 复制代码
  1. 李四存款 3600 ,当前余额为 13600     
  2. 王五取款 2700 ,当前余额为 10900     
  3. 老张存款 600 ,当前余额为 11500     
  4. 老牛取款 1300 ,当前余额为 10200     
  5. 胖子取款 800 ,当前余额为 9400     
  6. 张三存款 2000 ,当前余额为 11400     
  7.   
  8. Process finished with exit code  0   
李四存款3600,当前余额为13600 
王五取款2700,当前余额为10900 
老张存款600,当前余额为11500 
老牛取款1300,当前余额为10200 
胖子取款800,当前余额为9400 
张三存款2000,当前余额为11400 

Process finished with exit code 0
 
结合先前同步代码知识,举一反三,将此例改为同步代码块来实现,代码如下:
Java代码 复制代码
  1. import  java.util.concurrent.ExecutorService;    
  2. import  java.util.concurrent.Executors;    
  3.   
  4. /**   
  5. * Java线程:改为同步代码块   
  6.  
  7. * @author leizhimin 2009-11-5 10:57:29   
  8. */     
  9. public   class  Test {    
  10.          public   static   void  main(String[] args) {    
  11.                  //创建并发访问的账户    
  12.                 MyCount myCount =  new  MyCount( "95599200901215522"10000 );    
  13.                  //创建一个线程池    
  14.                 ExecutorService pool = Executors.newFixedThreadPool( 2 );    
  15.                 Thread t1 =  new  SaveThread( "张三" , myCount,  2000 );    
  16.                 Thread t2 =  new  SaveThread( "李四" , myCount,  3600 );    
  17.                 Thread t3 =  new  DrawThread( "王五" , myCount,  2700 );    
  18.                 Thread t4 =  new  SaveThread( "老张" , myCount,  600 );    
  19.                 Thread t5 =  new  DrawThread( "老牛" , myCount,  1300 );    
  20.                 Thread t6 =  new  DrawThread( "胖子" , myCount,  800 );    
  21.                  //执行各个线程    
  22.                 pool.execute(t1);    
  23.                 pool.execute(t2);    
  24.                 pool.execute(t3);    
  25.                 pool.execute(t4);    
  26.                 pool.execute(t5);    
  27.                 pool.execute(t6);    
  28.                  //关闭线程池    
  29.                 pool.shutdown();    
  30.         }    
  31. }    
  32.   
  33. /**   
  34. * 存款线程类   
  35. */     
  36. class  SaveThread  extends  Thread {    
  37.          private  String name;                 //操作人    
  38.          private  MyCount myCount;         //账户    
  39.          private   int  x;                             //存款金额    
  40.   
  41.         SaveThread(String name, MyCount myCount,  int  x) {    
  42.                  this .name = name;    
  43.                  this .myCount = myCount;    
  44.                  this .x = x;    
  45.         }    
  46.   
  47.          public   void  run() {    
  48.                 myCount.saving(x, name);    
  49.         }    
  50. }    
  51.   
  52. /**   
  53. * 取款线程类   
  54. */     
  55. class  DrawThread  extends  Thread {    
  56.          private  String name;                 //操作人    
  57.          private  MyCount myCount;         //账户    
  58.          private   int  x;                             //存款金额    
  59.   
  60.         DrawThread(String name, MyCount myCount,  int  x) {    
  61.                  this .name = name;    
  62.                  this .myCount = myCount;    
  63.                  this .x = x;    
  64.         }    
  65.   
  66.          public   void  run() {    
  67.                 myCount.drawing(x, name);    
  68.         }    
  69. }    
  70.   
  71.   
  72. /**   
  73. * 普通银行账户,不可透支   
  74. */     
  75. class  MyCount {    
  76.          private  String oid;                          //账号    
  77.          private   int  cash;                              //账户余额    
  78.   
  79.         MyCount(String oid,  int  cash) {    
  80.                  this .oid = oid;    
  81.                  this .cash = cash;    
  82.         }    
  83.   
  84.          /**   
  85.          * 存款   
  86.          *   
  87.          * @param x        操作金额   
  88.          * @param name 操作人   
  89.          */     
  90.          public   void  saving( int  x, String name) {    
  91.                  if  (x >  0 ) {    
  92.                          synchronized  ( this ) {    
  93.                                 cash += x;                     //存款    
  94.                                 System.out.println(name +  "存款"  + x +  ",当前余额为"  + cash);    
  95.                                 notifyAll();             //唤醒所有等待线程。    
  96.                         }    
  97.                 }    
  98.         }    
  99.   
  100.          /**   
  101.          * 取款   
  102.          *   
  103.          * @param x        操作金额   
  104.          * @param name 操作人   
  105.          */     
  106.          public   synchronized   void  drawing( int  x, String name) {    
  107.                  synchronized  ( this ) {    
  108.                          if  (cash - x <  0 ) {    
  109.                                  try  {    
  110.                                         wait();    
  111.                                 }  catch  (InterruptedException e1) {    
  112.                                         e1.printStackTrace();    
  113.                                 }    
  114.                         }  else  {    
  115.                                 cash -= x;                      //取款    
  116.                                 System.out.println(name +  "取款"  + x +  ",当前余额为"  + cash);    
  117.                         }    
  118.                 }    
  119.                 notifyAll();              //唤醒所有存款操作    
  120.         }    
  121. }  
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

/** 
* Java线程:改为同步代码块 
* 
* @author leizhimin 2009-11-5 10:57:29 
*/ 
public class Test { 
        public static void main(String[] args) { 
                //创建并发访问的账户 
                MyCount myCount = new MyCount("95599200901215522", 10000); 
                //创建一个线程池 
                ExecutorService pool = Executors.newFixedThreadPool(2); 
                Thread t1 = new SaveThread("张三", myCount, 2000); 
                Thread t2 = new SaveThread("李四", myCount, 3600); 
                Thread t3 = new DrawThread("王五", myCount, 2700); 
                Thread t4 = new SaveThread("老张", myCount, 600); 
                Thread t5 = new DrawThread("老牛", myCount, 1300); 
                Thread t6 = new DrawThread("胖子", myCount, 800); 
                //执行各个线程 
                pool.execute(t1); 
                pool.execute(t2); 
                pool.execute(t3); 
                pool.execute(t4); 
                pool.execute(t5); 
                pool.execute(t6); 
                //关闭线程池 
                pool.shutdown(); 
        } 
} 

/** 
* 存款线程类 
*/ 
class SaveThread extends Thread { 
        private String name;                //操作人 
        private MyCount myCount;        //账户 
        private int x;                            //存款金额 

        SaveThread(String name, MyCount myCount, int x) { 
                this.name = name; 
                this.myCount = myCount; 
                this.x = x; 
        } 

        public void run() { 
                myCount.saving(x, name); 
        } 
} 

/** 
* 取款线程类 
*/ 
class DrawThread extends Thread { 
        private String name;                //操作人 
        private MyCount myCount;        //账户 
        private int x;                            //存款金额 

        DrawThread(String name, MyCount myCount, int x) { 
                this.name = name; 
                this.myCount = myCount; 
                this.x = x; 
        } 

        public void run() { 
                myCount.drawing(x, name); 
        } 
} 


/** 
* 普通银行账户,不可透支 
*/ 
class MyCount { 
        private String oid;                         //账号 
        private int cash;                             //账户余额 

        MyCount(String oid, int cash) { 
                this.oid = oid; 
                this.cash = cash; 
        } 

        /** 
         * 存款 
         * 
         * @param x        操作金额 
         * @param name 操作人 
         */ 
        public void saving(int x, String name) { 
                if (x > 0) { 
                        synchronized (this) { 
                                cash += x;                    //存款 
                                System.out.println(name + "存款" + x + ",当前余额为" + cash); 
                                notifyAll();            //唤醒所有等待线程。 
                        } 
                } 
        } 

        /** 
         * 取款 
         * 
         * @param x        操作金额 
         * @param name 操作人 
         */ 
        public synchronized void drawing(int x, String name) { 
                synchronized (this) { 
                        if (cash - x < 0) { 
                                try { 
                                        wait(); 
                                } catch (InterruptedException e1) { 
                                        e1.printStackTrace(); 
                                } 
                        } else { 
                                cash -= x;                     //取款 
                                System.out.println(name + "取款" + x + ",当前余额为" + cash); 
                        } 
                } 
                notifyAll();             //唤醒所有存款操作 
        } 
}
 
Java代码 复制代码
  1. 李四存款 3600 ,当前余额为 13600     
  2. 王五取款 2700 ,当前余额为 10900     
  3. 老张存款 600 ,当前余额为 11500     
  4. 老牛取款 1300 ,当前余额为 10200     
  5. 胖子取款 800 ,当前余额为 9400     
  6. 张三存款 2000 ,当前余额为 11400     
  7.   
  8. Process finished with exit code  0  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值