黑马程序员技术交流社区
标题:
线程wait, notify 达不到效果,不理解
[打印本页]
作者:
冷漠无天
时间:
2013-11-21 09:50
标题:
线程wait, notify 达不到效果,不理解
为什么下面例子只输出:
print
---save
---save存入2000
sleep
xingle
例子:
package zhang11_Thread;
import java.util.concurrent.locks.ReentrantLock;
public class WaitNotifyTest {
public static void main(String[] args) {
ATMZhanghu atm = new ATMZhanghu("ATM",0);
SavePerson savep = new SavePerson(atm,2000);
PrintPerson printp = new PrintPerson(atm,2000);
Thread tp = new Thread(printp,"print");
Thread ts = new Thread(savep,"---save");
tp.start();
ts.start();
}
}
class ATMZhanghu{
private final ReentrantLock lock = new ReentrantLock();
private String name;
private int money;
private boolean falg = false;
public ATMZhanghu(String name,int money){
this.money = money;
this.name = name;
}
public synchronized void PrintMon(int printm) throws InterruptedException{
if(falg == true){
if(printm <= money){
System.out.println(Thread.currentThread().getName()+"取出"+printm);
System.out.println("sleep");
// Thread.sleep(1000);
System.out.println("xingle");
money -= printm;
}else{
System.out.println("钱不够");
}
System.out.println("余额:"+ money);
falg = false;
notifyAll();
}else{
wait();
}
}
public synchronized void SaveMon(int savem) throws InterruptedException{
if(falg == true){
wait();
}else{
System.out.println(Thread.currentThread().getName()+"存入"+savem);
System.out.println("sleep");
// Thread.sleep(1000);
System.out.println("xingle");
this.money +=savem;
falg = true;
notifyAll();
}
}
public ReentrantLock getLock() {
return lock;
}
public String getName() {
return name;
}
public int getMoney() {
return money;
}
public boolean isFalg() {
return falg;
}
}
class SavePerson implements Runnable{
private ATMZhanghu atmz;
private int savem;
public SavePerson(ATMZhanghu atm,int m){
this.atmz = atm;
this.savem = m;
}
public void run(){
System.out.println(Thread.currentThread().getName() + " " );
try {
atmz.SaveMon(savem);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class PrintPerson implements Runnable{
private ATMZhanghu atmz;
private int printm;
public PrintPerson(ATMZhanghu atm,int m){
this.atmz = atm;
this.printm = m;
}
public void run(){
System.out.println(Thread.currentThread().getName() + " " );
try {
atmz.PrintMon(printm);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
作者:
ysunday
时间:
2013-11-21 11:41
首先,你的代码很乱,尽量用工具栏中的<>
这个东西来贴代码,格式会好点。
然后
public synchronized void PrintMon(int printm) throws InterruptedException {
if (falg != true) {
我不缺定你这个flag是来标识什么的,我这边flag==true表示正在操作atm,否则不在操作
所以我把取钱的代码改成了if(flag != true)就是说,假如没有在操作
我才取钱,否则wait()
public synchronized void PrintMon(int printm) throws InterruptedException {
if (falg != true) {
if (printm <= money) {
System.out.println(Thread.currentThread().getName() + "取出"
+ printm);
System.out.println("sleep");
Thread.sleep(1000);
System.out.println("xingle");
money -= printm;
} else {
System.out.println("钱不够");
}
System.out.println("余额:" + money);
falg = false; //这里我把falg置成false,表示取钱完毕
notifyAll();
} else {
wait();
}
}
还有就是每次取完钱应该把标志置为false,表示取完了,没有人在操作取款机了
当改正了上边两处错误之后,起码你每次取钱和存钱都会有对应的输出了,不会只有
你陈述的那个输出了
2.线程的启动是有随机性的,虽然你先启动的取钱,但是有可能存钱线程启动之后
会抢占cpu执行,先执行完了存钱,也有可能先执行完取钱,这是不确定的
情况一:取钱先执行了
那么取钱的时候还没钱,就会输出没钱
然后执行存钱,正常输出存钱
执行结果如下
print
钱不够
余额:0
---save
---save存入2000
sleep
xingle
情况二;先执行完的存钱,正常输出存钱,
那么取钱再执行的时候就能正常取钱了,也正常输出
结果如下
---save
print
---save存入2000
sleep
xingle
print取出2000
sleep
xingle
余额:0
这个因为随机性很强,多运行几次就出结果了
复制代码
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2