2012-11-28 14 views
5

Ok, lo so che è probabblly mz cattiva comprensione di come le discussioni funzionano davvero, ma fino a quando qualcuno mi aiuta a capire io credo che sia un bug :)getName Discussione() restituisce il nome sbagliato

Nella mia classe principale e il suo metodo main() ho:

public static void main(String args[]){ 
    StoneBucket stoneBucket = new StoneBucket();  
    StonePutter spRunnable = new StonePutter(stoneBucket); 
    StoneThrower stRunnable = new StoneThrower(stoneBucket); 
    StoneThrower stRunnable2 = new StoneThrower(stoneBucket); 

    //Create the Threads that will take the Runnables as arguments 
    Thread puttingThread = new Thread(spRunnable); 
    Thread throwingThread = new Thread(stRunnable); 
    Thread throwingThread2 = new Thread(stRunnable); 

    puttingThread.setName("Putter"); 
    throwingThread.setName("Thrower 1"); 
    throwingThread2.setName("Thrower 2"); 
    [...] 

e poi nella mia classe StoneThrower ho

public class StoneThrower implements Runnable{ 

private StoneBucket sb; 
private String name; 

public StoneThrower(StoneBucket _sb){ 
    this.sb = _sb; 
} 

public void run(){ 

    name = Thread.currentThread().getName();   
    System.out.println("T::"+name+" started...");  
    int count = 0;  
    while(true){ 
      [...] 

Quando compilo ed eseguire questo codice sto ottenendo:

Screenshot of 2 threads...

Quindi, la mia domanda è: perché fare entrambe le cose di questi fili restituiscono lo stesso nome per currentThread().getName()? Quando sono stati creati, gli è stato assegnato il nome tramite threadX.setName("XXX") e questi vengono avviati chiamando threadX.start() ... Qualcuno potrebbe chiarirmi questo?

MODIFICA: Ho accettato la risposta corretta perché cambiando lo stRunnable in stRunnable2 il comportamento è come previsto. La vera domanda è ora perché succede questo. Creo due thread e li avvio separatamente. Come è possibile che il metodo run() (chiamato una volta quando il thread è stato creato) restituisca un nome errato?

+0

puoi pubblicare il pezzo di codice in cui si stanno avviando i fili? – PearsonArtPhoto

risposta

9

Ciò accade perché il nome del thread viene archiviato nella variabile di istanza name del numero StoneThrower. A causa della concorrenza, il secondo thread sostituisce il valore di name che il primo thread ha appena impostato e entrambi hanno lo stesso valore.

Ecco lo scenario:

1. Thread1#start 
2. Thread2#start 
3. Thread1#runnable#run -> runnable.name = 'Thrower 1' 
4. Thread2#runnable#run -> runnable.name = 'Thrower 2' // overrides 
5. Thread1#runnable#run -> System.out.println(runnable.name) 
6. Thread2#runnable#run -> System.out.println(runnable.name) 
+2

Infine una diagnosi ragionevole. +1 –

+0

Ho aggiunto un commento chiedendo questo.Grazie mille e scusa @NPE per aver preso il flag di risposta corretto :( – luigi7up

+0

Non ho visto l'intera implementazione di 'StoneThrower' ma molto probabilmente si può avere solo una sua istanza se si converte' name' in variabile locale. – hoaz

5

Si crea entrambi i fili con lo stesso eseguibile:

Thread throwingThread = new Thread(stRunnable); 
Thread throwingThread2 = new Thread(stRunnable); 
            ^^^^^^^^^^ stRunnable2? 

si memorizza il nome del filo in una variabile dell'oggetto Runnable istanza. Poiché l'oggetto è condiviso dai due thread, il secondo thread per eseguire name = Thread.currentThread().getName() sovrascrive il nome del primo thread con il proprio.

+1

Creazione di thread separati con lo stesso Runnable in sé non impone ai thread di avere lo stesso nome. Qualcos'altro sta succedendo. –

+0

@TedHopp: in questo caso, lo fa. Il nome del thread è memorizzato in una variabile di istanza dell'oggetto 'Runnable'. Poiché l'oggetto è condiviso dai due thread, il secondo thread esegue 'name = Thread.currentThread(). GetName()' vince. – NPE

+0

Sì, ma questo non faceva parte della tua risposta quando ho fatto quel commento. Con la modifica, ora guadagna il mio +1. –

Problemi correlati