2010-12-30 21 views
8

si pongo un hilo para dormir en un bucle, netbeans me da una advertencia diciendo que invocar Thread.sleep en loop puede causar problemas de rendimiento. Sin embargo, si tuviera que reemplazar el sueño con join, no se da tal precaución. Ambas versiones compilan y funcionan bien aunque. Mi código está debajo (revise las últimas líneas para "Thread.sleep() vs t.join()").Thread sleep y 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!"); 
    } 
} 

como yo lo entiendo, se unen espera a que el otro hilo para completar, pero en este caso, enviaban el sueño y se unen a hacer lo mismo? Entonces, ¿por qué Netbeans lanza la precaución?

+0

este http://stackoverflow.com/questions/3535754/netbeans-java-new-hint-thread-sleep-called-in-loop puede ayudar – pmu

+1

@prateek, sí, en realidad vi ese hilo antes de publicarlo. sin embargo, esa pregunta es completamente diferente (sé la causa de la advertencia pero no sé por qué lo hace en este caso). ¡gracias por tu aporte! ¡muy apreciado! –

Respuesta

28

Hay una diferencia entre join() y sleep(). join() esperará hasta que el tiempo de espera expire o la cadena termine. sleep() solo esperará la cantidad de tiempo especificada a menos que se interrumpa. Por lo tanto, es perfectamente posible que join() regrese mucho más rápido que el tiempo especificado.

La razón por la que Netbeans te advierte sobre el sueño() y no sobre join() es precisamente esa diferencia. join() espera algo significativo mientras Sleep() simplemente se queda allí sin hacer nada. Si no estás esperando algo, ¿por qué querrías esperar? Raramente es significativo, de ahí la advertencia.

+0

¡ah, ya veo! Creo que esta es la única respuesta que respondió mi qn correctamente. gracias por su ayuda sergey! –

5

Que se puedan usar para lograr lo mismo no significa que se abuse de la misma manera. La gente a menudo abusan Thread.sleep(), cuando en realidad deberían usar una cerradura o algo que los bloques:

// 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

gracias por la ayuda! Supongo que mi qn sería este: ¿cuál es la diferencia entre dormir y unirse? parece que no tengo ninguno en este caso ... –

+1

En su caso, no hay diferencia; Netbeans simplemente da una advertencia para 'sleep()'. –

+0

Creo que unirse es mejor que usar un candado ... –

1

Para este caso, creo que la unión es una alternativa mejor que el uso de una cerradura .. JOIN es simple y elegante. Pero si usa un bloqueo, también debe usar el método de notificación y el bloque sincronizado y, por supuesto, necesita un objeto de bloqueo.

join sample, calling thread code;

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

ejemplo de bloqueo: código de paso de llamada;

Objeto lock = new Object();

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(); 
    } 

}

Aquí es código t1 hilo;

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

    } 
+0

gracias por su ayuda Gursel, muy apreciada. Estoy de acuerdo, los bloqueos son definitivamente mejores. pero mi qn fue abt sleep y join, y que ambos funcionan igual en este caso específico. –