2012-07-28 66 views
6

Me han dicho que utilizar Thread.Sleep() es una mala solución a veces que uno quisiera hacer un intervalo de tiempo dentro de un bucle de acciones en un método sincronizado.Thread.Sleep alternativa en Java

Por otro lado, tengo dos subprocesos diferentes que están activos durante el tiempo de ejecución de mi programa y también un objeto compartido y cuando uso Object.wait (long) en ese objeto compartido, causa que mi GUI se congele durante algún tiempo.

¿cuál sería una mejor solución para este problema?


actualización Esta parte del código está incluyendo uno de los hilos que está comenzando en GUI:

class temperatureUp extends Thread { @Override public void run() { while(true) { try { GBC.increaseTemp(); updateSystemStatus(); } catch(Exception ex) { StringWriter w = new StringWriter(); ex.printStackTrace(new PrintWriter(w)); txtLog.setText(w + "\n" + txtLog.getText()); } } } };

y este es el método sincronizado en objeto compartido, GBC:

public synchronized void increaseTemp() throws InterruptedException{ 
    // don't increase the temperature if the boiler 
    // is not turned on... 
    while (!isBoilerOn) 
     wait(); 

    // increase the current temperature 
    if ((currentTemp + 1) < MAX_TEMP && currentTemp < desiredTemp) { 
     Thread.sleep(2000); ///what should put here if not thread sleep? 
     currentTemp ++;  
     updateGasBoilerStatus(); 
    } 
} 
+1

Debe estar causando que [la secuencia de distribución de eventos] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html) espere. ¿Podría proporcionar un pequeño ejemplo en el código de cómo inicia sus hilos y cuándo llama a wait()? – theon

+1

Eche un vistazo a ['SwingWorker'] (http://docs.oracle.com/javase/6/docs/api/javax/swing/SwingWorker.html). Además, vea ['this answer'] (http://stackoverflow.com/a/11546203/597657) para saber cómo está funcionando. –

+0

@theon Actualicé la publicación y agregué una parte del código. – Afflatus

Respuesta

4

Puede reducir el alcance de la declaración synchronize. Por ejemplo, si está realizando la sincronización de todo el método

public synchronized void foo() 

Podría quitar el modificador y el uso de un bloque sincronizado lugar

synchronized (this) { 
    // ... 
} 

y mover el Thread.sleep() fuera de este bloque si es posible. Solo sincronice en aquellas declaraciones que modifiquen estados de datos compartidos.

Muchos de los problemas de subprocesos relacionados con Swing están relacionados con el Event Dispatcher Thread y se pueden resolver fácilmente con él. Te recomiendo que leas.

Un poco de historia poco, ¿por qué no debería llamar Thread.sleep() dentro de un bloque de sincronización:

de albergue o en espera mientras se mantiene un bloqueo. Llamar a Thread.sleep con un bloqueo puede evitar que otros hilos progresen durante un tiempo largo de y, por lo tanto, es un riesgo de vitalidad potencialmente grave. Llamar a Object.wait o Condition.await con dos bloqueos retenidos plantea un peligro similar . [JCIP]

+1

Gracias, leeré el artículo en The Event Dispatch Thread y le responderé en caso de que tuviera otra pregunta. – Afflatus

+0

@Elham En su caso, creo que todo el capítulo de * Concurrency in Swing * ayudará, ya que el EDT es para actualizar los componentes de Swing y su problema de sincronización consiste en modificar los estados de su modelo. –

+0

en realidad la parte de actualización funciona bien. el problema es que me gustaría esperar después de cada actualización para que el usuario vea el resultado del proceso que se realiza por hilos paso a paso. – Afflatus

7

No dormir dentro del método sincronizado! ¡No espere en los manejadores de eventos GUI/métodos!

Divida las acciones sincronizadas para que la llamada Sleep() no se invoque en el contexto de la secuencia de comandos de la GUI.

Quizás use InvokeLater() para el segundo bit.

+0

Ya he desactivado el comando sleep en la GUI. el método sincronizado está en otra clase que, como dije, es un objeto compartido que está siendo utilizado por dos hilos diferentes al mismo tiempo. – Afflatus

0

Me gustaría hacer uso de monitores: http://www.artima.com/insidejvm/ed2/threadsynch4.html Tal vez con notificar o notificar Todo lo que pueda resolverlo. ¡Buena suerte!

+0

Gracias, pero la cosa es la espera y notificar que el hilo funciona bien en el programa. Mi problema es que quiero que la presentación de incrementos en la GUI sea más lenta para que el usuario la vea. – Afflatus

0

Mantenga siempre su subproceso Event Dispatcher Thread (EDT) que es responsable de manejar su GUI, lejos de cualquier trabajo que no sea de UI.Además, no sincronizar el método completo, pero sincronizar los enunciados atómicos

synchronized(this){ 
    //... 
} 
+0

bien, gracias, pero ¿cómo va a ser esta una respuesta a mi pregunta? – Afflatus

+0

y las únicas tres acciones que se han puesto en mi método sincronizado son las que son necesarias para estar bajo el mismo bloqueo en esta secuencia. No puedo reducir el alcance más. – Afflatus

-1

Puede probar este siguiente código:

public static void delay(int waitTime) { 
     long endTime = System.currentTimeMillis() + (waitTime * 1000); 
     while (System.currentTimeMillis() < endTime) {} 
    } 

llamada como retardo (5). Y el control esperará por 5 segundos.

+0

No lo use, es muy complicado. Un alternativo sería usar java.util.Timer –

Cuestiones relacionadas