黑马程序员技术交流社区
标题:
多线程并发执行(银行存钱取钱操作)
[打印本页]
作者:
李贺晓
时间:
2012-11-21 14:17
标题:
多线程并发执行(银行存钱取钱操作)
//定义银行账户
class Account
{
private String accountnum;
private double money;
private boolean flag=false;
Account(String accountnum,double money)
{
this.accountnum=accountnum;
this.money=money;
}
public void setAccountnum(String accountnum)
{
this.accountnum=accountnum;
}
public String getAccountnum()
{
return accountnum;
}
public double getMoney()
{
return this.money;
}
public int hashCode()
{
return accountnum.hashCode();
}
public boolean equals(Object obj)
{
if(obj!=null && obj.getClass()==Account.class)
{
Account a=(Account) obj;
return a.getAccountnum().equals(accountnum);
}
return false;
}
public synchronized void pullMoney(double pullmoney)
{
try
{
if(!flag)
{
wait();
}
else
{
System.out.print(Thread.currentThread().getName()+"取钱:"+pullmoney);
money=money-pullmoney;
System.out.println(",账户余额为:"+money);
flag=false;
notifyAll();
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public synchronized void pushMoney(double pushmoney)
{
try
{
if(flag)
{
wait();
}
else
{
System.out.print(Thread.currentThread().getName()+"存钱:"+pushmoney);
money=money+pushmoney;
System.out.println(",账户余额为:"+money);
flag=true;
notifyAll();
}
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
class PullThread extends Thread
{
private Account account;
private double pullmoney;
PullThread(){}
PullThread(String name,Account account,double pullmoney)
{
super(name);
this.account=account;
this.pullmoney=pullmoney;
}
public void run()
{
for(int i=0;i<10;i++)
{
account.pullMoney(pullmoney);
}
}
}
class PushThread extends Thread
{
private Account account;
private double pushmoney;
PushThread(String name,Account account,double pushmoney)
{
super(name);
this.account=account;
this.pushmoney=pushmoney;
}
public void run()
{
for(int i=0;i<10;i++)
{
account.pushMoney(pushmoney);
}
}
}
class Test2
{
public static void main(String[] args)
{
Account a=new Account("123456",0);
PullThread p=new PullThread("甲取钱",a,500);
p.start();
PushThread p1=new PushThread("已存钱",a,500);
p1.start();
}
}
我设置的是存钱取钱个10次,但是运行后,为什么是存钱取钱各5次啊?
是哪里出的问题,求解答
作者:
李贺晓
时间:
2012-11-21 17:20
{:soso_e101:}怎么没人解答下
作者:
廖力
时间:
2012-11-21 19:03
本帖最后由 廖力 于 2012-11-21 19:05 编辑
在你的run方法中分别加入
System.out.println("push " + i);
复制代码
和
System.out.println("pull " + i);
复制代码
打印的结果是
pull 0
push 0
已存钱存钱:500.0,账户余额为:500.0
push 1
甲取钱取钱:500.0,账户余额为:0.0
pull 1
push 2
已存钱存钱:500.0,账户余额为:500.0
push 3
pull 2
甲取钱取钱:500.0,账户余额为:0.0
pull 3
push 4
已存钱存钱:500.0,账户余额为:500.0
push 5
pull 4
甲取钱取钱:500.0,账户余额为:0.0
pull 5
push 6
已存钱存钱:500.0,账户余额为:500.0
push 7
pull 6
甲取钱取钱:500.0,账户余额为:0.0
pull 7
push 8
已存钱存钱:500.0,账户余额为:500.0
push 9
pull 8
甲取钱取钱:500.0,账户余额为:0.0
pull 9
具体原因我也不知道为什么
但是最好把wait sleep直接放在run方法里面
还有notifyAll尽量少用 因为容易出先java.lang.IllegalMonitorStateException的异常
下面是我改的 不知道你是不是这个意思...
package com.test5;
//定义银行账户
class Account {
private String accountnum;
private double money;
Account(String accountnum, double money) {
this.accountnum = accountnum;
this.money = money;
}
public void setAccountnum(String accountnum) {
this.accountnum = accountnum;
}
public String getAccountnum() {
return accountnum;
}
public double getMoney() {
return this.money;
}
public int hashCode() {
return accountnum.hashCode();
}
public boolean equals(Object obj) {
if (obj != null && obj.getClass() == Account.class) {
Account a = (Account) obj;
return a.getAccountnum().equals(accountnum);
}
return false;
}
public synchronized void pullMoney(double pullmoney) {
System.out.print(Thread.currentThread().getName() + "取钱:" + pullmoney);
money = money - pullmoney;
System.out.println(",账户余额为:" + money);
}
public synchronized void pushMoney(double pushmoney) {
System.out.print(Thread.currentThread().getName() + "存钱:" + pushmoney);
money = money + pushmoney;
System.out.println(",账户余额为:" + money);
}
}
class PullThread extends Thread {
private Account account;
private double pullmoney;
PullThread(String name, Account account, double pullmoney) {
super(name);
this.account = account;
this.pullmoney = pullmoney;
}
public void run() {
for (int i = 0; i < 10;) {
if (account.getMoney() >= pullmoney) {
account.pullMoney(pullmoney);
i++;
long time = System.currentTimeMillis();
try {
Thread.sleep(333);
} catch (InterruptedException e) {
e.printStackTrace();
}
time = System.currentTimeMillis() - time;
System.out.println("第" + i + "次取钱耗时" + time + "毫秒");
} else {
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
class PushThread extends Thread {
private Account account;
private double pushmoney;
private PullThread pt;
public void setPt(PullThread pt) {
this.pt = pt;
}
PushThread(String name, Account account, double pushmoney) {
super(name);
this.account = account;
this.pushmoney = pushmoney;
}
public void run() {
for (int i = 0; i < 10; i++) {
account.pushMoney(pushmoney);
long time = System.currentTimeMillis();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
time = System.currentTimeMillis() - time;
System.out.println("第" + i + "次存钱耗时" + time + "毫秒");
synchronized (pt) {
pt.notify();
}
}
}
}
public class Test2 {
public static void main(String[] args) {
Account a = new Account("123456", 0);
PushThread p1 = new PushThread("乙存钱", a, 500);
PullThread p2 = new PullThread("甲取钱", a, 500);
p1.setPt(p2);
p1.start();
p2.start();
}
}
复制代码
~
作者:
李贺晓
时间:
2012-11-22 11:30
廖力 发表于 2012-11-21 19:03
在你的run方法中分别加入和打印的结果是
pull 0
push 0
嗯,你这种方法是不错,但是我按照我写的应该也是没问题的啊,也没有造成死锁,但是就是不知道为什么只能存钱取钱各5次,不知道是怎么回事
作者:
徐强
时间:
2012-11-22 14:07
应为当wait()线程被唤醒后,这个线程没什么要做的就直接结束了,所以只打印出5次。你在wait()后面加上
System.out.print(Thread.currentThread().getName() + "取钱:"
+ pullmoney);
money = money - pullmoney;
System.out.println(",账户余额为:" + money);
flag = false;
复制代码
段代码就能打印10次
class Account {
private String accountnum;
private double money;
private boolean flag = false;
Account(String accountnum, double money) {
this.accountnum = accountnum;
this.money = money;
}
public void setAccountnum(String accountnum) {
this.accountnum = accountnum;
}
public String getAccountnum() {
return accountnum;
}
public double getMoney() {
return this.money;
}
public int hashCode() {
return accountnum.hashCode();
}
public boolean equals(Object obj) {
if (obj != null && obj.getClass() == Account.class) {
Account a = (Account) obj;
return a.getAccountnum().equals(accountnum);
}
return false;
}
public synchronized void pullMoney(double pullmoney) {
try {
if (!flag) {
System.out.println("取钱等待");
wait();
//线程被唤醒后要做的事
System.out.println("取钱激活");
System.out.print(Thread.currentThread().getName() + "取钱:"
+ pullmoney);
money = money - pullmoney;
System.out.println(",账户余额为:" + money);
flag = false;
} else {
System.out.print(Thread.currentThread().getName() + "取钱:"
+ pullmoney);
money = money - pullmoney;
System.out.println(",账户余额为:" + money);
flag = false;
notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized void pushMoney(double pushmoney) {
try {
if (flag) {
wait();
//线程被唤醒后要做的事
System.out.print(Thread.currentThread().getName() + "存钱:"
+ pushmoney);
money = money + pushmoney;
System.out.println(",账户余额为:" + money);
flag = true;
} else {
System.out.print(Thread.currentThread().getName() + "存钱:"
+ pushmoney);
money = money + pushmoney;
System.out.println(",账户余额为:" + money);
flag = true;
notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class PullThread extends Thread {
private Account account;
private double pullmoney;
PullThread() {
}
PullThread(String name, Account account, double pullmoney) {
super(name);
this.account = account;
this.pullmoney = pullmoney;
}
public void run() {
for (int j = 0; j < 10; j++) {
account.pullMoney(pullmoney);
System.out.println("----"+Thread.currentThread().getName().toString());
}
}
}
class PushThread extends Thread {
private Account account;
private double pushmoney;
PushThread(String name, Account account, double pushmoney) {
super(name);
this.account = account;
this.pushmoney = pushmoney;
}
public void run() {
for (int i = 0; i < 10; i++) {
account.pushMoney(pushmoney);
System.out.println("----"+Thread.currentThread().getName());
}
}
}
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2