2016-02-23 3 views
0

Итак, я пытаюсь разобраться с этим в течение нескольких часов, и я уверен, что его что-то действительно простое или просто ошибка, которую я пропускаю, но у меня есть трехклассная программа, контроль, учетная запись и MyThreads.Почему мои потоки не просыпаются после notifyAll();

Я пытаюсь использовать многопользовательские потоки (карты) для изменения одной учетной записи, я пытаюсь использовать монитор, поэтому только один поток может вносить изменения за раз, это не то, что я архивировал. Я как-то просто разрешил один поток, чтобы получить доступ к классу учетной записи и никому другому, они, кажется, просто исчезают, я предполагаю, что они просто все ждут, но отказываются просыпаться ... любая помощь, прежде чем я буду взорваться?

учетный код:

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."); 
    } 

    } 

Я знаю его беспорядок, прости им лень.

+0

Y Вы использовали блокировку переменной? –

+0

Когда вы объявили метод как синхронизированный, практически не используется переменная блокировки –

ответ

0

Посмотрите на определение монитора на Java. В коде используется ключевое слово synchronized для двух методов, которые являются такими же, как:

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

    } finally { 
     lock.unlock(); 
    } 
} 

Короче говоря, это является обобщающим для явного блокировки и предотвратить несколько потоков для доступа к методам одновременно.

Итак, просто удалите часть lock (т. Е. Блок while(lock==1)) внутри ваших методов synchronized и он будет работать. Кроме того, если в других кодах вам нужен реальный замок, используйте класс Lock, а не целое число.

Для получения дополнительной информации, есть много хорошего представления о многопоточности в Интернете, например this one.

+0

спасибо Я удалил материал блокировки, но мои потоки все еще изменяют данные одновременно, что приводит к ошибкам значения и количества. – Jamie

+0

что заставляет вас так говорить? – Derlin

0

Ваш вопрос, и, таким образом, ответ, представляет собой замечательную смесь статических синхронизированных и ожидающих уведомлений, которые вызывают нев. Зачем использовать статические? звучит как волшебное слово? пропустить статику и сделать жизнь проще.

Также обратите внимание, что уведомление о ожидании связано с конкретным объектом; если wait-notify связаны с разными объектами, они не будут связываться. Имейте один объект, который все они синхронизируют.

Смежные вопросы