2016-02-23 85 views
0

所以我一直試圖把這個問題解決了幾個小時,我確定它很簡單或者只是一個簡單的錯誤,但我有一個三級程序,控制,帳戶和MyThreads。爲什麼我的線程不會在notifyAll()後喚醒;

我試圖讓multipule線程(卡)修改單個帳戶,我試圖使用一個監視器,所以只有一個線程可以在一次進行更改,這不是我已存檔我不知何故只是允許一個線程訪問帳戶類,沒有其他人,他們似乎只是消失,我認爲他們只是在等待,但拒絕醒來......任何幫助之前,我內爆?

科目代碼:

class account{ 
private static int value = 0; 
private static int cards = 0; 
private static int count = 0; 
private static int lock = 0; 


public void setValue(int temp){ 
value = temp; 
} 

public int getValue(){ 

// while(lock == 1){ 
// try{ 
//  wait(); 
// }catch (InterruptedException e){ 
// } 
// } 
return value; 
} 

synchronized public void withdraw(int temp, String tempID){ 
while(lock == 1){ 
try{ 
wait(); 
}catch (InterruptedException e){} 
} 

lock=1; 
value= value - temp; 
count++; 
System.out.println(count + "(" + tempID +")"+" "+temp+" - "+value); 
lock = 0; 

this.notifyAll(); 

} 


synchronized public void deposit(int temp, String tempID){ 
while(lock == 1){ 
try{ 
wait(); 
}catch (InterruptedException e){} 
} 

lock=1; 
value= value + temp; 
count++; 
System.out.println(count + "(" + tempID +")"+" - "+temp+" "+value); 
lock = 0; 
this.notifyAll(); 
} 

public void setCards(int temp){ 
cards = temp; 
} 


public int getCards(){ 
return cards; 
} 

public int getCount(){ 
return count; 
} 
} 

控制代碼:

class control{ 

public static void main(String [] args){ 

account acc = new account(); 

acc.setValue(1000); 

acc.setCards(5); 


// if(args.length > 0){ 
//  try{ 
//  int tempCards = Integer.parseInt(args[0]); 
//  
//  }catch (NumberFormatException e) { 
//  System.err.println("Number of Cards : " + args[0] + " must be an integer."); 
//  System.exit(1); 
//  } 
//  try{ 
//  int tempVal = 0; 
//  tempVal = Integer.parseInt(args[1]); 
//  acc.setValue(tempVal); 
//  }catch (NumberFormatException e) { 
//  System.err.println("Account Value : " + args[1] + " must be an integer."); 
//  System.exit(1); 
//  } 
// }else{ 
//  System.err.println("No values found, please start program with the number of Cards and Bank Account Value, both in integer format"); 
//  System.exit(1); 
// } 


System.out.println("Transaction Withdrawal Deposit Balance"); 
System.out.println("         " + acc.getValue()); 

for(int i=0; i<=((acc.getCards())-1); i++){ 
new MyThreads(Integer.toString(i+1)); 

} 
} 
} 

MyThreads代碼:

class MyThreads implements Runnable{ 
private String ID; 
private Thread t; 

account acc = new account(); 
MyThreads(String tempID){ 
ID = tempID; 
t = new Thread(this, ID); 
t.start(); 
} 


public void run(){ 

try{ 

for (int i = 0; i < 20; i++){ 


    if(Math.random()>0.5){ 

    int tempW = 0; 

    tempW = ((int)(Math.random()*100)); 

    acc.withdraw(tempW, this.ID); 

    //System.out.println(acc.getCount() + "(" + this.ID +")"+" "+tempW+" -"+acc.getValue()); 

    }else{ 

    int tempD = 0; 
    tempD = ((int)(Math.random()*100)); 
    acc.deposit(tempD, this.ID); 
    //System.out.println(acc.getCount() + "(" + this.ID +")"+" "+" - "+tempD+" "+acc.getValue()); 

    } 

    t.sleep(500); 
    } 
    } catch (InterruptedException e) { 
    System.out.println("Thread " + ID + " interrupted."); 
    } 
    System.out.println("Thread " + ID + " exiting."); 
    } 

    } 

我知道它的一個爛攤子,原諒我的懶惰IM。

+0

Y你有沒有使用鎖定變量? –

+0

當你聲明方法爲synchronized時,幾乎沒有使用鎖變量 –

回答

0

查看Java中Monitor的定義。在您的代碼,您可以使用關鍵字​​兩種方法,這是一樣的:

public void XX(){ 
    lock.lock(); // lock is a private variable 
    try { 
     // code here 

    } finally { 
     lock.unlock(); 
    } 
} 

總之,這是一個明確的鎖定的簡寫,並防止多個線程同時訪問方法。

因此,只需刪除​​方法中的lock部分(即while(lock==1)塊),它就可以工作。另外,如果在其他代碼中需要真正的鎖,請使用Lock類,而不是整數。

欲瞭解更多信息,有很多很好的介紹在線多線程,例如this one

+0

謝謝我刪除了鎖的東西,但我的線程似乎仍然在同時修改數據,導致值和count變量出錯。 – Jamie

+0

是什麼讓你這麼說? – Derlin

0

你的問題,因此答案,是一個靜態同步和等待通知,這是neve被稱爲美妙的混合物。爲什麼使用靜態?聽起來像一個魔法字?跳過靜態並讓生活更輕鬆。

另請注意,wait-notify與特定對象有關;如果等待通知與不同的對象有關,它們將不會通信。有一個他們全都同步的單個對象。