Condition用法--实现线程间的通信

本文介绍Java5中Condition的用法,通过银行存取款案例解析如何利用Condition实现线程间通信,避免传统wait和notify方法的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

java5 Condition用法--实现线程间的通信

Condition的功能类似在传统线程技术中的Object.wait()和Object.natify()的功能,传统线程技术实现的互斥只能一个线程单独干,不能说这个线程干完了通知另一个线程来干,Condition就是解决这个问题的,实现线程间的通信。比如CPU让小弟做事,小弟说我先歇着并通知大哥,大哥就开始做事。

Condition 将 Object 监视器方法(wait、notify 和 notifyAll)分解成截然不同的对象,以便通过将这些对象与任意 Lock 实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock 替代了 synchronized 方法和语句的使用,Condition 替代了 Object 监视器方法的使用。

Condition实例实质上被绑定到一个锁上。要为特定 Lock 实例获得 Condition 实例,请使用其 newCondition() 方法。

在java5中,一个锁可以有多个条件,每个条件上可以有多个线程等待,通过调用await()方法,可以让线程在该条件下等待。当调用signalAll()方法,又可以唤醒该条件下的等待的线程。

下面以银行存取款案例阐述Condition用法:

假设有一个账户,多个用户(线程)在同时操作这个账户,有的存款有的取款,存款随便存,取款有限制,不能透支,任何试图透支的操作都将等待里面有足够存款才执行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package  com.ljq.test.thread;
 
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;
 
public  class  ConditionTest {
     public  static  void  main(String[] args) {
         ConditionTest test =  new  ConditionTest();
 
         // 创建并发访问的账户
         Account myAccount = test. new  Account( "95599200901215522" 10000 );
         // 创建一个线程池
         ExecutorService pool = Executors.newFixedThreadPool( 2 );
         Thread t1 = test. new  DrawThread( "张三" , myAccount,  11000 );
         Thread t2 = test. new  SaveThread( "李四" , myAccount,  3600 );
         Thread t3 = test. new  DrawThread( "王五" , myAccount,  2700 );
         Thread t4 = test. new  SaveThread( "老张" , myAccount,  600 );
         Thread t5 = test. new  DrawThread( "老牛" , myAccount,  1300 );
         Thread t6 = test. new  SaveThread( "胖子" , myAccount,  2000 );
 
         // 执行各个线程
         pool.execute(t1);
         pool.execute(t2);
         pool.execute(t3);
         pool.execute(t4);
         pool.execute(t5);
         pool.execute(t6);
         // 关闭线程池
         pool.shutdown();
     }
 
     /**
      * 存款线程类
      */
     public  class  SaveThread  extends  Thread {
         private  String name;  // 操作人
         private  Account account;  // 账户
         private  int  x;  // 存款金额
 
         SaveThread(String name, Account account,  int  x) {
             this .name = name;
             this .account = account;
             this .x = x;
         }
 
         public  void  run() {
             account.saving(x, name);
         }
     }
 
     /**
      * 取款线程类
      */
     public  class  DrawThread  extends  Thread {
         private  String name;  // 操作人
         private  Account account;  // 账户
         private  int  x;  // 存款金额
 
         DrawThread(String name, Account account,  int  x) {
             this .name = name;
             this .account = account;
             this .x = x;
         }
 
         public  void  run() {
             account.drawing(x, name);
         }
     }
 
     /**
      * 银行账户
      */
     public  class  Account {
         private  String id;  // 账号
         private  int  cash;  // 账户余额
         private  Lock lock =  new  ReentrantLock();  // 账户锁
         private  Condition _save = lock.newCondition();  // 存款条件
         private  Condition _draw = lock.newCondition();  // 取款条件
 
         Account(String id,  int  cash) {
             this .id = id;
             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 ) {
                     System.out.println(name +  "取款失败[余额不足],取款"  + x +  ",当前余额为"  + cash);
                     _draw.await();  // 阻塞取款操作
                 else  {
                     cash -= x;  // 取款
                     System.out.println(name +  "取款"  + x +  ",当前余额为"  + cash);
                 }
                 _save.signalAll();  // 唤醒所有等待的存款操作
             catch  (InterruptedException e) {
                 e.printStackTrace();
             finally  {
                 lock.unlock();  // 释放锁
             }
         }
     }
     
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值