¿Cómo pausar y luego reanudar un hilo?

Declaro que he leído sobre el hilo, pero nunca lo he usado. Así que te pregunto 🙂

Tengo dos hilos: A y B , donde A gestiona la GUI y B maneja la lógica.

Yo comenzaría con A

Luego, cuando A dibuje la GUI, la pondría en pausa, para esperar a que B llegue a un punto X en el método de ejecución.

Y cuando B alcanza el punto X en el método de ejecución, hago una pausa en B y reanudo A

A y B comparten alguna variable para administrar la GUI, y la lógica …

¿Puedo hacerlo? si es así, ¿cómo? 🙂

Usando los métodos wait () y notify () :

wait () – Hace que el subproceso actual espere hasta que otro subproceso invoque el método notify () o el método notifyAll () para este objeto.

notify () – Despierta un hilo único que está esperando en el monitor de este objeto.

Puede bloquear subprocesos utilizando los métodos de wait y notify de la clase Object, pero puede ser complicado hacerlo bien. Aquí hay un ejemplo dentro de un bucle infinito en Runnable:

 public class Example implements Runnable { private volatile boolean running = true; private volatile boolean paused = false; private final Object pauseLock = new Object(); @Override public void run () { while (running){ synchronized (pauseLock) { if (!running) { // may have changed while waiting to // synchronize on pauseLock break; } if (paused) { try { pauseLock.wait(); // will cause this Thread to block until // another thread calls pauseLock.notifyAll() // Note that calling wait() will // relinquish the synchronized lock that this // thread holds on pauseLock so another thread // can acquire the lock to call notifyAll() // (link with explanation below this code) } catch (InterruptedException ex) { break; } if (!running) { // running might have changed since we paused break; } } } // Your code here } } public void stop() { running = false; // you might also want to interrupt() the Thread that is // running this Runnable, too, or perhaps call: resume(); // to unblock } public void pause() { // you may want to throw an IllegalStateException if !running paused = true; } public void resume() { synchronized (pauseLock) { paused = false; pauseLock.notifyAll(); // Unblocks thread } } }; 

(Para obtener más información sobre por qué necesitamos sincronizar como se ilustra arriba mientras notifyAll wait y notifyAll , consulte el tutorial de Java sobre el tema ).

Si otro subproceso llama al método pause() este ejecutable, entonces el subproceso que ejecuta el ejecutable se bloqueará cuando llegue al principio del ciclo while.

Tenga en cuenta que no es posible pausar un hilo en ningún punto arbitrario. Necesita el hilo para comprobar periódicamente si debe pausar y bloquearse a sí mismo si es así.

Esperaría que no necesites pausar el hilo de la GUI. El sistema operativo se encargará de eso, y debe estar listo para responder en caso de que el usuario haga algo.

Otro pensamiento es asegurarse de que las variables compartidas estén sincronizadas correctamente entre los dos hilos. Intenté responder a una pregunta relacionada con eso recientemente, mira aquí .

puedes usar un CountDownLatch . Cuando el hilo A tiene que esperar, el hilo B llamará a countDownLatchInstance.await(); Cuando B llega al punto X invocará countDownLatchInstance.countDown() ; permitiendo que A continúe su flujo de ejecución.

Cuando tu dices

A gestiona la GUI

Espero que no te refieras a la UI/Main Thread

,

Así es como recibí la espera de thread y notifiqué que funcionaba para mí:

 public class Main { public static void main(String[] args) { final Object lock = new Object(); MyThread t = new MyThread(); t.lock = lock; t.run(); while(true){ try { synchronized (lock) { lock.wait(); } System.out.println("hello"); } catch (InterruptedException e) { e.printStackTrace(); } } } 

}

clase pública MyThread extends Thread {

 Object lock; @Override public void run(){ JFrame fr = new JFrame("Anothing"); JButton btn = new JButton("Next"); btn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { synchronized (lock) { lock.notify(); } } }); fr.setLayout(new FlowLayout()); fr.add(btn); fr.setSize(400, 400); fr.setVisible(true); } 

}

Luego, cada vez que presiono el botón, el otro hilo se despierta, ejecuta una ronda y espera un nuevo clic.

La primitiva java para suspender y reanudar un hilo está en desuso. Consulte esto para saber cómo puede lograr lo mejor que necesita: http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html Compruebe cómo puede hacer el equivalente a suspender y reanudar

¿Qué debería usar en lugar de Thread.suspend y Thread.resume ?

Al igual que con Thread.stop , el enfoque prudente es hacer que la encuesta “thread objective” sea una variable que indique el estado deseado de la cadena (activa o suspendida). Cuando se suspende el estado deseado, el hilo espera usando Object.wait . Cuando se reanuda el hilo, el hilo objective se notifica utilizando Object.notify .

El código de ejemplo se da en la misma respuesta para ayudarte a lograr esto.