2010-12-30 25 views
8

se metto un thread in sleep in un ciclo, netbeans mi avvisa dicendo che invocare thread.sleep in loop può causare problemi di prestazioni. Tuttavia, se dovessi sostituire il sonno con il join, non viene data tale cautela. Entrambe le versioni sono compilate e funzionano benissimo. Il mio codice è sotto (controlla le ultime poche righe per "Thread.sleep() vs t.join()").Thread sleep e thread join

public class Test{ 

    //Display a message, preceded by the name of the current thread 
    static void threadMessage(String message) { 
     String threadName = Thread.currentThread().getName(); 
     System.out.format("%s: %s%n", threadName, message); 
    } 

    private static class MessageLoop implements Runnable { 
     public void run() { 
      String importantInfo[] = { 
       "Mares eat oats", 
       "Does eat oats", 
       "Little lambs eat ivy", 
       "A kid will eat ivy too" 
      }; 
      try { 
       for (int i = 0; i < importantInfo.length; i++) { 
        //Pause for 4 seconds 
        Thread.sleep(4000); 
        //Print a message 
        threadMessage(importantInfo[i]); 
       } 
      } catch (InterruptedException e) { 
       threadMessage("I wasn't done!"); 
      } 
     } 
    } 

    public static void main(String args[]) throws InterruptedException { 


     //Delay, in milliseconds before we interrupt MessageLoop 
     //thread (default one hour). 
     long patience = 1000 * 60 * 60; 

     //If command line argument present, gives patience in seconds. 
     if (args.length > 0) { 
      try { 
       patience = Long.parseLong(args[0]) * 1000; 
      } catch (NumberFormatException e) { 
       System.err.println("Argument must be an integer."); 
       System.exit(1); 
      } 

     } 

     threadMessage("Starting MessageLoop thread"); 
     long startTime = System.currentTimeMillis(); 
     Thread t = new Thread(new MessageLoop()); 
     t.start(); 

     threadMessage("Waiting for MessageLoop thread to finish"); 
     //loop until MessageLoop thread exits 
     while (t.isAlive()) { 
      threadMessage("Still waiting..."); 
      //Wait maximum of 1 second for MessageLoop thread to 
      //finish. 
      /*******LOOK HERE**********************/ 
      Thread.sleep(1000);//issues caution unlike t.join(1000) 
      /**************************************/ 
      if (((System.currentTimeMillis() - startTime) > patience) && 
        t.isAlive()) { 
       threadMessage("Tired of waiting!"); 
       t.interrupt(); 
       //Shouldn't be long now -- wait indefinitely 
       t.join(); 
      } 

     } 
     threadMessage("Finally!"); 
    } 
} 

se ho capito bene, si uniscono attende l'altro thread per completare, ma in questo caso, arent sia il sonno e si uniscono facendo la stessa cosa? Allora perché netbeans lancia la cautela?

+0

questo http://stackoverflow.com/questions/3535754/netbeans-java-new-hint-thread-sleep-called-in-loop può aiutare – pmu

+1

@prateek sì, in realtà ho visto quella discussione prima di postare. tuttavia, quella domanda è completamente diversa (conosco la causa della cautela ma non so perché lo faccia in questo caso). Grazie per la tua indicazione, comunque! molto apprezzato! –

risposta

28

C'è una differenza tra join() e sleep(). join() attenderà fino al termine del timeout o al termine del thread. sleep() attenderà solo il tempo specificato a meno che non venga interrotto. Quindi è perfettamente possibile che join() ritorni molto più veloce del tempo specificato.

Il motivo per cui Netbeans ti avvisa di sleep() e non di join() è proprio questa differenza. join() attende qualcosa di significativo mentre il sonno() rimane seduto lì senza fare nulla. Se non stai aspettando qualcosa, allora perché vorresti aspettare? È raramente significativo, da qui l'avvertimento.

+0

ah, vedo! Credo che questa sia l'unica risposta che ha risposto correttamente al mio qn. grazie per il tuo aiuto sergey! –

5

Il fatto che possano essere utilizzati per ottenere la stessa cosa non significa che vengano abusati allo stesso modo. La gente spesso abusano Thread.sleep() quando dovrebbe davvero usare un blocco o qualcosa che blocchi:

// Allow others to notify me when there's work to do 
synchronized (lock) { 
    try { 
     lock.wait(); // Much better than a loop with sleep 
    } catch(InterruptedException e) { 
     // someone killed me 
     return; 
    } 
} 


// or use a BlockingQueue or similar 
Job job = queue.get(); 
if (job instanceof ExitJob) return; 
+0

grazie per l'aiuto! immagino che il mio qn sarebbe questo- qual è la differenza tra dormire e partecipare? in questo caso non mi sembra nessuno ... –

+1

Nel tuo caso, non c'è differenza; Netbeans dà solo un avvertimento per 'sleep()'. –

+0

Penso che l'unione sia migliore alaternativa di un blocco ... –

1

Per questo caso, penso che è meglio unirsi a un'alternativa rispetto all'utilizzo di un blocco .. join è semplice ed elegante. Ma se si utilizza un blocco, è necessario utilizzare anche il metodo di notifica e il blocco sincronizzato e ovviamente è necessario un oggetto di blocco ..

unire l'esempio, chiamando il codice del thread;

t1.start(); 
System.out.println("waiting for thread t1"); 
t1.join(); 
System.out.println("thread t1 has finished its job"); 

esempio di blocco: chiamata del codice di thread;

Blocco oggetto = nuovo oggetto();

synchronized(lock) { 
    try { 
     t1.start(); 
     System.out.println("waiting for thread t1"); 
     lock.wait(); 
     System.out.println("thread t1 has finished its job"); 
    }catch (InterruptedException ex) { 
      e.printStackTrace(); 
    } 

}

Ecco filo codice t1;

synchronized(lock) { 
     try { 
      System.out.println("doing heavy work"); 
      // ..... 
      lock.notify(); 
      }catch (InterruptedException ex) { 
       e.printStackTrace(); 
     } 

    } 
+0

grazie per il tuo aiuto Gursel, molto apprezzato. concordo, le serrature sono decisamente migliori. ma il mio qn era addormentato e si univa, e che entrambi funzionavano allo stesso modo in questo caso specifico. –