题目:模拟银行取款,使用三种线程同步方法实现取款的安全。编写如下类,并进行取款测试:
账户类:Account,含余额字段balance
取款类:DrawMoney,在指定帐户中进行取款操作
编写线程体:实现取款操作的安全
方法1:同步代码块
/**
* 银行帐户
*/
class Account {
/**
* 余额
*/
private double balance;
/**
* 构造方法
* @param balance
*/
Account(double balance) {
super();
this.balance = balance;
}
//getter . setter
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
class ATM implements Runnable{
/**
* 需要取的金额
*/
private double drawMoney;
String str = new String("");//做同步代码块的监听对象
/**
* 帐户
*/
private Account a;
ATM(double drawMoney, Account a) {
super();
this.drawMoney = drawMoney;
this.a = a;
}
public void run() {
synchronized (str) {
if(a.getBalance()>=drawMoney){
System.out.println(Thread.currentThread().getName()+"吐出了"+drawMoney+"元");
a.setBalance(a.getBalance()-drawMoney);//修改余额
}else
{
System.out.println("Your account don't have enough money!");
}
}
}
}
public class DrawMoneyDemo {
public static void main(String[] args) {
Account a = new Account(1000);
ATM atm = new ATM(800,a);//从a帐户中取800元
//假设有两个线程进行同时操作
new Thread(atm, "A").start();
new Thread(atm, "B").start();
}
}
执行结果为:
B吐出了800.0元
Your account don't have enough money!
我们将具有原子性的代码放入 synchronized 代码块中,形成同步代码块。这样,在同一时刻只能有一个线程进入代码块执行该段代码。
格式为:
synchronized(object){
//代码块
}
方法2:同步方法
在帐户类中定义一个同步方法实现取款操作,这样线程执行时,只能互斥的调用该方法
/**
* 银行帐户
*/
class Account {
/**
* 余额
*/
private double balance;
/**
* 构造方法
*
* @param balance
*/
Account(double balance) {
super();
this.balance = balance;
}
// getter . setter
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
/**
* 使用同步方法的方式进行取款
* @param drawMoney
* 取款金额
*/
public synchronized void draw(double drawMoney) {
if (this.getBalance() >= drawMoney) {
System.out.println(Thread.currentThread().getName() + "吐出了"
+ drawMoney + "元");
this.setBalance(this.getBalance() - drawMoney);// 修改余额
} else {
System.out.println("Your account don't have enough money!");
}
}
}
class ATM implements Runnable {
/**
* 需要取的金额
*/
private double drawMoney;
/**
* 帐户
*/
private Account a;
ATM(double drawMoney, Account a) {
super();
this.drawMoney = drawMoney;
this.a = a;
}
public void run() {
a.draw(drawMoney);
}
}
public class DrawMoneyDemo {
public static void main(String[] args) {
Account a = new Account(1000);
ATM atm = new ATM(800, a);// 从a帐户中取800元
// 假设有两个线程进行同时操作
new Thread(atm, "A").start();
new Thread(atm, "B").start();
}
}
执行结果为:
A吐出了800.0元
Your account don't have enough money!
方法3:利用Java5的同步锁机制实现线程同步
import java.util.concurrent.locks.ReentrantLock;
/**
* 银行帐户
*/
class Account {
/**
* 余额
*/
private double balance;
// 定义可重入锁
private final ReentrantLock lock = new ReentrantLock();
/**
* 构造方法
*
* @param balance
*/
Account(double balance) {
super();
this.balance = balance;
}
// getter . setter
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
/**
* 使用可重入锁的方式进行取款
*
* @param drawMoney
* 取款金额
*/
public void draw(double drawMoney) {
lock.lock();// 加锁
try {
if (this.getBalance() >= drawMoney) {
System.out.println(Thread.currentThread().getName() + "吐出了"
+ drawMoney + "元");
this.setBalance(this.getBalance() - drawMoney);// 修改余额
} else {
System.out.println("Your account don't have enough money!");
}
} finally {
lock.unlock();// 释放锁
}
}
}
class ATM implements Runnable {
/**
* 需要取的金额
*/
private double drawMoney;
/**
* 帐户
*/
private Account a;
ATM(double drawMoney, Account a) {
super();
this.drawMoney = drawMoney;
this.a = a;
}
public void run() {
a.draw(drawMoney);
}
}
public class DrawMoneyDemo {
public static void main(String[] args) {
Account a = new Account(1000);
ATM atm = new ATM(800, a);// 从a帐户中取800元
// 假设有两个线程进行同时操作
new Thread(atm, "A").start();
new Thread(atm, "B").start();
}
}
执行结果为:
A吐出了800.0元
Your account don't have enough money!
对于可重入锁,其格式为:
public class X
{
private final ReentrantLock lock = new ReentrantLock();
//定义需要保证线程安全的方法
public void m(){
//加锁
lock.lock();
try{
//... method body
}finally{
//在finally释放锁
lock.unlock();
}
}
}
使用ReentrantLock可重入锁对象可以显示的加锁和解锁,其具有与使用synchronized方法和语句所访问的隐式监听器锁相同的一些基本行为和语义,但功能更强大。