1.模拟银行取钱的问题
1.定义一个Account类
1)该Account类封装了账户编号(String)和余额(double)两个属性
2)设置相应属性的getter和setter方法
3)提供无参和有两个参数的构造器
4)系统根据账号判断与用户是否匹配,需提供hashCode()和equals()方法的重写
在我们重写hashCode()方法后,可以看到两个属性值完全相同的对象,他们的哈希值是相同的。从业务的角度来说,达到了这两个对象相同的目的。
2.提供两个取钱的线程类:小明、小明’s wife
1)提供了Account类的account属性和double类的取款额的属性
2)提供带线程名的构造器
3)run()方法中提供取钱的操作
3.在主类中创建线程进行测试。考虑线程安全问题。
- 利用lock和接口Runnable
package com.lianxi.thread;
import java.util.concurrent.locks.ReentrantLock;
public class Account2 {
private final ReentrantLock lock=new ReentrantLock(true);
private String id;
private double balance;
public void setBalance(double balance) {
this.balance = balance;
}
public double getBalance() {
return balance;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Account2(String id,double balance){
this.balance=balance;
this.id=id;
}
public Account2(){
}
@Override
public int hashCode() {
final int a=31;
int result=1;
result =a*result+((id==null)?0:id.toUpperCase().hashCode());
long temp;
temp=Double.doubleToLongBits(balance);
result=a*result+(int)(temp^(temp>>>32));
return result;
}
@Override
public boolean equals(Object obj) {
if (obj==this){
return obj==this;
}
if (obj instanceof Account2){
Account2 account2= (Account2) obj;
return this.id.equals(account2.id);
}
return false;
}
@Override
public String toString() {
return "账户编号:"+id+",余额:"+balance;
}
public void save(double money){
lock.lock();
try {
if (money > 0&&balance >= money) {
balance-=money;
System.out.println(Thread.currentThread().getName() + ":取款成功,取款金额为:" + money);
} else {
System.out.println(Thread.currentThread().getName()+"取款失败,余额不足");
}
}finally {
System.out.println("账户编号:"+id+",余额:"+balance);
lock.unlock();
}
}
}
class WithdrawMoney2 implements Runnable{
public Account2 account2;
public Thread thread;
private double money;//取款金额
public WithdrawMoney2(Account2 account2,double money){
this.account2=account2;
this.money=money;
}
@Override
public void run() {
account2.save(money);
}
}
class AccountTest{
public static void main(String[] args){
Account2 account2=new Account2("2003",2000);
WithdrawMoney2 w1=new WithdrawMoney2(account2,200);
WithdrawMoney2 w2=new WithdrawMoney2(account2,300);
WithdrawMoney2 w3=new WithdrawMoney2(account2,300);
Thread t1=new Thread(w1);
Thread t2=new Thread(w2);
Thread t3=new Thread(w3);
t1.setName("lilining");
t2.setName("zhengzijun");
t3.setName("3");
t1.start();
t2.start();
t3.start();
//System.out.println(account2);
}
}
- 利用继承Thread和synchronized
package com.lianxi.thread;
public class Account {
private String id;//账户编号
private double balance;//余额
public Account(){//无参构造器
}
public Account(String id,double balance){//有参构造器
this.balance=balance;
this.id=id;
}
public String getId() {
return id;
}
public void setId(String id){
this.id=id;
}
public double getBalance(){
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
/**
* 在我们重写hashCode()方法后,可以看到两个属性值完全相同的对象,
* 他们的哈希值是相同的。从业务的角度来说,达到了这两个对象相同的目的。
* toUpperCase()--转换为大写的字符串
* @return
*/
@Override
public int hashCode() {
final int p=31;
int a=1;
a=p*a+((id==null)?0:id.toUpperCase().hashCode());
return a;
}
/**
* 系统根据账号判断与用户是否匹配
* @param obj
* @return
*/
@Override
public boolean equals(Object obj) {
//地址相等
if (this==obj){
return this==obj;
}
//如果两个对象的账户编号相等,我们认为相等
if (obj instanceof Account) {
Account a = (Account) obj;
return this.id.equals(a.id);
}
return false;
}
class WithdrawMoney extends Thread{
Account account;
private double money;//取款金额
public WithdrawMoney(){
}
public WithdrawMoney(String name,Account account,double money){
super(name);
this.account=account;
this.money=money;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public void run() {
synchronized (account) {
if (account.getBalance() > 0 && account.getBalance() >=money) {
System.out.println(Thread.currentThread().getName()+":取款成功,取款金额为:"+money);
try {
Thread.sleep(100);
}catch (InterruptedException e){
e.printStackTrace();
}
account.setBalance(account.getBalance() - money);
} else {
System.out.println("余额不足");
}
System.out.println("现在账户的余额为:"+account.getBalance());
}
}
}
class AccountText{
public static void main(String[] args){
Account a=new Account("10001",2000);
WithdrawMoney w1=new WithdrawMoney("小明",a,2000);
WithdrawMoney w2=new WithdrawMoney("小明老婆",a,300);
w1.start();
w2.start();
}
}