为什么又写了线程同步(2)呢,因为感觉编程这个事情真的是很神奇呀,同样一个需求,由不同的人去分析,去编写会产生完全 不同的代码,还是上次那题,今天这篇写一些老师讲解的思路和内容
其实个人认为条条大路通罗马,能解决问题都是好办法,但是本人目前处于学习阶段,能解决问题固然是好的,但是我觉得更重要的是培养一个好的解题思路或者讲说是符合业内编程规范的代码写法,虽然说每个人的脑回路是不同的,但是代码毕竟不是给自己一个人看的。
—— 以上为个人拙见,如有不对还望指正~~
再放一下上次的题目:
利用多线程实现男孩存钱,女孩取钱的功能:
1,有一个银行账户Account类,此类中有余额属性private int balance;并且可以进行存、取钱功能
2,有Boy和Girl类都实现了Runnable接口,这两个类在主体方法中可以操作Account类中的存取钱方法
3,测试类进行检验男孩存钱,女孩取钱
提示:1,男孩女孩肯定是操作同一个银行账户,
2,可以使用Math.Random()方法完成存取钱的数目
3,同时,女孩取钱太多时,应该不成功,需要等到男孩再存钱,之后再取
这次直接放上老师讲解的代码,思路分析我写到注释里了
public class AAAA {
//main方法主要写对于其他方法的调用以及创建写好的各个类
public static void main(String[] args) {
//账户类对象account,新开户需要账户中有钱,这里假定为100
Account account = new Account(1000);
//Boy类对象boy,将账户交到boy手中
Boy boy = new Boy(account);
//Girl类对象girl,将同一个账户交到girl手中
Girl girl = new Girl(account);
//因为Boy和Girl类都实现的是Runnable接口,所以需要包装为线程类,同时为了好区分,设置线程名
Thread t1 = new Thread(boy, "男孩");
Thread t2 = new Thread(girl, "女孩");
//启动两个线程
t1.start();
t2.start();
}
}
//账户类
class Account{
//只有一个私有变量,账户余额
private int balance;
//无参构造器
public Account() {}
//单参构造器,设置账户余额
public Account(int balance) {
this.balance = balance;
}
//存钱方法,使用synchronized关键字将该段代码锁起来,写在普通方法前锁对象为this
public synchronized void cunqian(int num){
//传入存钱数目,并增加数目到余额
balance+=num;
//输出相关信息
System.out.println("男孩存了:"+num+"银行卡中总共还有:"+balance+"元");
//因为下面女孩取钱时余额不足时会wait()所以男孩存完钱使用notify()唤醒女孩
notify();
}
//和上面一样,使用synchronized使两个线程在此时同步执行
public synchronized void quqian(int num){
//与存钱方法不同,取钱时要先判断余额是否充足
if (num>balance) {
//余额不足时输出信息并且使调用该方法的线程进入wait()状态
System.out.println("女孩取了"+num+"元钱,太多了,余额:"+balance+"不足,需要等待男孩存钱");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
//如果余额充足,则直接减去要取出的金额
balance-=num;
//这里使用.err输出只是为了使控制台显示的时候好辨别男孩和女孩的行为
System.err.println("女孩取了"+num+"元钱,余额:"+balance);
}
}
}
//Boy类实现Runnable接口
class Boy implements Runnable{
Account account;
//单参构造函数,要求传入一个账户
public Boy(Account account) {
super();
this.account = account;
}
public Boy() {}
@Override
public void run() {
while (true) {
int aaa = (int) (Math.random() * 1000);
account.cunqian(aaa);
try {
Thread.sleep(aaa*5);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//Girl类实现Runnable接口
class Girl implements Runnable{
Account account;
public Girl() {}
//单参构造函数,要求传入一个账户
public Girl(Account account) {
this.account = account;
}
@Override
public void run() {
while (true) {
int aaa = (int) (Math.random() * 1000);
//使用Account类中的取钱方法
account.quqian(aaa);
try {
Thread.sleep(aaa);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
运行结果: