Manera más eficiente de pausar el bucle deseado

¿Es posible reescribir este código para trabajar mejor con el procesador? Tengo una clase, que hace algunas tareas con periodicy fijo en un hilo separado. A veces este proceso puede ser detenido y reanudado. Actualmente estoy utilizando una bandera para pausar, funciona bien, pero el bucle de esta manera todavía carga el procesador cuando el proceso está en pausa. ¿Es posible arreglar esto?

private boolean mIsCanceled = false; private boolean mIsPaused = true; // TODO more efficient for processor way of pausing is required private final Thread mTimerThread = new Thread(new Runnable() { @Override public void run() { while(!mIsCanceled){ try { Thread.sleep(UPDATE_PERIOD); } catch (InterruptedException e) { e.printStackTrace(); } if (!mIsPaused){ doStep(); } } } }); public MyClass(){ mTimerThread.start(); } private void pause(){ mIsPaused = true; } private void resume(){ mIsPaused = false; } private void doStep(){ // Some code } 

Por favor, proporcione una implementación alternativa de mi código.

PS El entorno es Android OS 2.2+

4 Solutions collect form web for “Manera más eficiente de pausar el bucle deseado”

Las herramientas disponibles son:

wait / notify – todos estamos tratando de escapar de este sistema arcaico.

Semaphore s – una vez que su hilo lo ha agarrado, usted lo sostiene hasta que la liberación lo agarra de nuevo no bloquea. Esto significa que no puedes pausar desde dentro de tu propio hilo.

CyclicBarrier – Debe ser creado de nuevo cada vez que se utiliza.

ReadWriteLock – Mi favorito. Puedes tener tantos hilos deteniéndote como quieras y solo reanudarás cuando todos ellos hayan llamado a resume . Incluso puede detenerse si lo desea.

 import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * PauseableThread is a Thread with pause/resume and cancel methods. * * The meat of the process must implement `step`. * * You can either extend this and implement `step` or use the factory. * * Note that I cannot extend Thread because my resume will clash with Thread's deprecated one. * * Usage: Either write a `Stepper` and run it in a `PausableThread` or extend `PausableThread` and call `blockIfPaused()` at appropriate points. */ public abstract class PauseableThread implements Runnable { // The lock. // We'll hold a read lock on it to pause the thread. // The thread will momentarily grab a write lock on it to pause. // This way you can have multiple pausers using normal locks. private final ReadWriteLock pause = new ReentrantReadWriteLock(); // Flag to cancel the wholeprocess. private volatile boolean cancelled = false; // The exception that caused it to finish. private Exception thrown = null; @Override // The core run mechanism. public void run() { try { while (!cancelled) { // Block here if we're paused. blockIfPaused(); // Do my work. step(); } } catch (Exception ex) { // Just fall out when exception is thrown. thrown = ex; } } // Block if pause has been called without a matching resume. private void blockIfPaused() throws InterruptedException { try { // Grab a write lock. Will block if a read lock has been taken. pause.writeLock().lockInterruptibly(); } finally { // Release the lock immediately to avoid blocking when pause is called. pause.writeLock().unlock(); } } // Pause the work. NB: MUST be balanced by a resume. public void pause() { // We can wait for a lock here. pause.readLock().lock(); } // Resume the work. NB: MUST be balanced by a pause. public void resume() { // Release the lock. pause.readLock().unlock(); } // Stop. public void cancel() { // Stop everything. cancelled = true; } // start - like a thread. public void start() { // Wrap it in a thread. new Thread(this).start(); } // Get the exceptuion that was thrown to stop the thread or null if the thread was cancelled. public Exception getThrown() { return thrown; } // Create this method to do stuff. // Calls to this method will stop when pause is called. // Any thrown exception stops the whole process. public abstract void step() throws Exception; // Factory to wrap a Stepper in a PauseableThread public static PauseableThread make(Stepper stepper) { StepperThread pauseableStepper = new StepperThread(stepper); // That's the thread they can pause/resume. return pauseableStepper; } // One of these must be used. public interface Stepper { // A Stepper has a step method. // Any exception thrown causes the enclosing thread to stop. public void step() throws Exception; } // Holder for a Stepper. private static class StepperThread extends PauseableThread { private final Stepper stepper; StepperThread(Stepper stepper) { this.stepper = stepper; } @Override public void step() throws Exception { stepper.step(); } } // My test counter. static int n = 0; // Test/demo. public static void main(String[] args) throws InterruptedException { try { // Simple stepper that just increments n. Stepper s = new Stepper() { @Override public void step() throws Exception { n += 1; Thread.sleep(10); } }; PauseableThread t = PauseableThread.make(s); // Start it up. t.start(); Thread.sleep(1000); t.pause(); System.out.println("Paused: " + n); Thread.sleep(1000); System.out.println("Resuminng: " + n); t.resume(); Thread.sleep(1000); t.cancel(); } catch (Exception e) { } } } 

Editar: Código modificado para ser de uso más general.

Sus mejores opciones son utilizar wait () / notify () o simplemente cambiar a ScheduledExecutorService

El uso apropiado de wait () / notify () puede ser complicado. Recomiendo encarecidamente "Java Concurrency in Practice" para aprender más sobre el enhebrado.

Creo que la mejor manera aquí sería usar Thread.wait para el hilo de espera en lugar de dormir, y usar Thread.notify en el hilo que está esperando. Más información aquí: http://www.javamex.com/tutorials/synchronization_wait_notify.shtml

Usted puede mejorar la eficiencia drástica mediante el uso de un monitor en lugar de dormir el hilo. Usted acaba de hacer bloques en su código con una palabra clave sincronizada. Y un objeto final que actúa el monitor. Mire uP más en la API en los monitores.

FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.