多线程实现存款取款
我们在做一些比较大的项目的时候,可能需要用到多线程,比如我们做一个银行系统,最基本的操作,存钱,取钱。
当我们跑单线程时候存钱取钱无所谓。当我们用多线程的时候就会对线程的共享资源比如用户的余额进行控制,
保证只能存钱进程或者取钱进程中的一个进程去访问共享资源即余额。下面看实现:
package Test;
class Account {
String name;
double balance;
public Account(String name) {
this.name=name;
this.balance=0;
}
public synchronized void put(double value) {
if(value>0)
this.balance+=value;
System.out.println("您的存款金额为"+value+"存款成功,余额为"+this.balance);
}
public synchronized double get( double value) {
if(value<=0)
return 0;
if(value<=this.balance)
this.balance-=value;
else {
value=this.balance;
this.balance=0;
}
System.out.println("您的取款金额为"+value+"取款成功,余额为"+this.balance);
return value;
}
}
class SaveThread extends Thread{
private Account account;
private double value;
public SaveThread(Account account,double value) {
this.account=account;
this.value=value;
}
public void run() {
try {Thread.sleep(1);}
catch(InterruptedException ex) {}
this.account.put(this.value);
}
}
class FetchThread extends Thread{
private Account account;
private double value;
public FetchThread(Account account,double value){
this.account = account;
this.value = value;
}
public void run(){
try{
Thread.sleep(1);
}
catch(InterruptedException ex){}
this.account.get(this.value);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Account wang =new Account("Wang");
(new SaveThread(wang,100)).start();
(new SaveThread(wang,200)).start();
(new FetchThread(wang,300)).start();
}
}
我们对get()取钱和put()存钱方法加上了锁。然后有一个取钱线程和存钱线程同时执行,由于余额是共享资源只会允许
一个线程来访问他,所以会有上面执行的结果。
当然由于线程的执行顺序是不确定的,所以上面程序的结果也可能是这样的:
也可能是这样的:
这是由于线程执行顺序不确定性引起的,而且get取钱函数的写的是如果余额大于要取的钱,则取出。如果余额不够,
则取出全部余额。尽管余额为0,也不会报错。
提高优先级来让线程执行的顺序有规律也是不可靠的。可以用join来控制先执行哪个线程。或者用信号量来控制。