Tengo un objeto Game ejecutable. El juego se juega a través de Twitter, así que cuando el Juego llega a un punto en el que se necesita la entrada del jugador, tengo una función como esta:
private synchronized void waitForInput() { input = ""; while(input == ""){ System.out.println("Waiting..."); try{ synchronized(this){ // wait for a second then continue to check the loop condition this.wait(1000); } } catch(Exception e){ System.out.println("failed to wait."); e.printStackTrace(); } } System.out.println("Finished waiting."); }
La private volatile String input
es una variable de instancia de la clase Player. Tengo un Twitter Listener esperando que alguien envíe un tweet al bot, luego, al recibir dicho tweet, toma el texto del tweet como entrada y establece esta variable de instancia, saliendo del ciclo. No estoy particularmente contento con este enfoque, ya que la espera no tiene sentido aquí, y no hay necesidad de usar notificar () aquí, parece que me estoy acercando a esto mal. Sin embargo, no tengo idea de cómo podría esperar () y luego también acceder a la entrada de la variable de instancia para actualizarla, ya que el hilo está en el bloque sincronizado y no puede ejecutar el método setter para la entrada.
¿Alguien tiene alguna idea para un mejor enfoque?
Al llamar a wait()
necesita un bloque synchronized
, pero libera el bloqueo tan pronto como está esperando. Recuperará automáticamente el bloqueo cuando se despierte. Así que su código debería verse así... No es necesario usar ningún tiempo de espera...
private void waitForInput() { String input = ""; // Though we are not waiting infinitely without timeout, we still need // while loop. // Since JVM in some cases might wake-up thread without notify calls, // this is called "spurious" wake-ups. synchronized (this) { while (input.equals("")) { System.out.println("Waiting..."); try { this.wait();//Wait infinitely, or till notify called. //Lock is released but current thread is blocked, so call on some Async thread if required. } catch (Exception e) { System.out.println("failed to wait."); e.printStackTrace(); } } } System.out.println("Finished waiting."); } //Your twitter bot should call this method, when new input received. public void wakeup(String input) { synchronized (this) { this.input = input; notifyAll(); } }