java 线程同步condtion_Java:多线程,使用同步锁(Lock)时利用Condition类实现线程间通信...

[我们不仅可以使用synchronized来实现多线程同步,还可以通过创建锁对象来实现多线程的同步,还是上次模拟取现的操作,这次利用lock对象实现同步,下面是代码:    import

如果程序不使用synchronized关键字来保证同步,而是直接使用Lock对象来保证同步,则系统中不存在隐式的同步监视器,也就不能用wait()、notify()、notifyAll()方法进行线程通信了。当使用Lock对象来保证同步时,Java提供了Condition类来协调线程间的通信。

本示范简单模拟银行帐户的存取款活动,帐户余额大于等于取款金额时允许取款;帐户余额小于1000时允许存款(这与真实业务逻辑不符合,只是技术上需要才如此做的,否则存款一下子全存完就不好玩了)。[1>Lock:        Lock比传统线程模型中的Synchronied方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码段要实现同步互斥的效果,它们必须用同

1. 实体Account类

package com.clzhang.sample.thread;

import java.util.concurrent.locks.Lock;

import java.util.concurrent.locks.Condition;

import java.util.concurrent.locks.ReentrantLock;

public class Account {

// 锁对象

private final Lock lock = new ReentrantLock();

// Condition对象

private final Condition condDeposit = lock.newCondition();

private final Condition condWithdraw = lock.newCondition();

// 为避免double类型计算的误差,balance类型设计为int的

private int balance;

public Account(int balance) {

this.balance = balance;

}

public void withdraw(int drawAmount) {

// 加锁

lock.lock();

try {

// 如果帐户余额不足,则取钱方法阻塞

while (balance < drawAmount)

condWithdraw.await();

// 执行取钱

balance -= drawAmount;

System.out.println(Thread.currentThread().getName() + " 取钱:" + drawAmount + "账户余额为:"

+ balance);

// 唤醒存款线程

condDeposit.signal();

} catch (InterruptedException ex) {

ex.printStackTrace();

} finally {

lock.unlock();

}

}

// 按照目前设计,帐户余额大于1000后不让存款,必须先取款后才能再存。

// 这与真实业务逻辑不符合,只是技术上需要才如此做的,否则存款一下子全存完就不好玩了。

public void deposit(int depositAmount) {

lock.lock();

try {

// 如果帐户余额大于1000,存钱方法阻塞

while (balance > 1000)

condDeposit.await();

// 执行存款

balance += depositAmount;

System.out.println(Thread.currentThread().getName() + " 存款:" + depositAmount + "账户余额为:"

+ balance);

// 唤醒取款线程

condWithdraw.signal();

} catch (InterruptedException ex) {

ex.printStackTrace();

} finally {

lock.unlock();

}

}

}

2. 调用类(DepositDrawTest类)

package com.clzhang.sample.thread;

class DrawThread extends Thread {

// 模拟用户账户

private Account account;

// 每次取钱数

private int drawAmount;

public DrawThread(String name, Account account, int drawAmount) {

super(name);

this.account = account;

this.drawAmount = drawAmount;

}

@Override

public void run() {

for (int i = 0; i < 3; i++) {

account.withdraw(drawAmount);

try {

Thread.sleep(100);

} catch (InterruptedException e) {

}

}

}

}

class DepositThread extends Thread {

// 模拟用户账户

private Account account;

// 每次存钱数

private int depositAmount;

public DepositThread(String name, Account account, int depositAmount) {

super(name);

this.account = account;

this.depositAmount = depositAmount;

}

@Override

public void run() {

for (int i = 0; i < 3; i++) {

account.deposit(depositAmount);

try {

Thread.sleep(100);

} catch (InterruptedException e) {

}

}

}

}

public class DepositDrawTest {

public static void main(String[] args) {

// 创建一个账户,初始帐户余额为0

Account acct = new Account(0);

// 注意下面的取款与存款的balance参数值需要匹配,

// 否则可能造成存款过多而不让存,然后又没有人取款导致程序无法正常终止的问题。

new DrawThread("取钱者1", acct, 400).start();

new DrawThread("取钱者2", acct, 600).start();

new DepositThread("存款者甲", acct, 600).start();

new DepositThread("存款者乙", acct, 200).start();

new DepositThread("存款者丙", acct, 400).start();

}

}

输出:

存款者甲 存款:600账户余额为:600

存款者乙 存款:200账户余额为:800

存款者丙 存款:400账户余额为:1200

取钱者1 取钱:400账户余额为:800

取钱者2 取钱:600账户余额为:200

存款者乙 存款:200账户余额为:400

存款者甲 存款:600账户余额为:1000

取钱者2 取钱:600账户余额为:400

存款者丙 存款:400账户余额为:800

取钱者1 取钱:400账户余额为:400

存款者甲 存款:600账户余额为:1000

存款者丙 存款:400账户余额为:1400

取钱者1 取钱:400账户余额为:1000

存款者乙 存款:200账户余额为:1200

取钱者2 取钱:600账户余额为:600

3. 总结

如果取款金额大于余额则不让取款,等存款队列继续存钱,余额足够支付时再让取款。

如果存款过多(大于1000),则存款不让存了,等取款队列把钱取走,余额降低到1000以下时,可以继续存款。

这样就允许多次连续取款(只要帐户有钱),多次连续存款(余额不能大于1000),而不是存款、取款依次调用。[ 线程之间除了同步互斥,还要考虑通信。在Java5之前我们的通信方式为:wait 和 notify。那么Condition的优势是支持多路等待,就是我可以定义多个Condition,每个condition

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值