Pregunta

Estoy tratando de aprender la API de concurrencia Java, y para mi ejercicio quiero programar un trabajo para ejecutar periódicamente cada x segundos. El trabajo calculará un número aleatorio.

Quiero obtener el resultado de la tarea programada tan pronto como esté terminado. No pude hacer esto solo con la API, así que lo pirateé.

¿Hay alguna manera de hacerlo mejor, sin usar mecanismos de bajo nivel? Me gustaría poder eliminar la sincronización en MyRandomGiverTask.getResult() y en su lugar usa algo como el ScheduledFuture.get(). Pero en mi código, ProgramedFuture nunca se realiza/se completa. Esta es mi solución actual:

class A {
    public static void main() {
        MyRandomGiverTask task = new MyRandomGiverTask(200);
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
        ScheduledFuture<Double> scheduledDouble =
            (ScheduledFuture<Double>) scheduler
                .scheduleAtFixedRate(task, 1, 4, TimeUnit.SECONDS);
        while (true) {
            System.out.println(" >> " + task.getResult());
        }
    }
    public class MyRandomGiverTask implements Runnable {
        MyRandomGiver giver = new MyRandomGiver();
        int param;
        double result;
        public MyRandomGiverTask(int param) { this.param = param; }
        @Override public void run() { result = giver.getRandom(param); }
        public double getResult() {
            try {
                while (result == 0d) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                return result;
            } finally {
                result = 0d;
            }
        }
    }
}
¿Fue útil?

Solución

Si desea calcularse cada número aleatorio, use un Bloquingqueue. las tareas programadas put()s nuevos números aleatorios en la cola y lo que sea que los quiera puede take() a ellos.

Además, si tu fueron va a usar algo como su solución, querrá usar wait()/notify(), no sleep().

Otros consejos

Su tarea está programada a una tasa fija. Esto significa que hasta que cancele la tarea, el albacea la ejecutará una y otra vez con una tasa fija. Lo único que tal tarea puede hacer es tener un efecto secundario. No puede devolver nada, ya que el futuro devuelto por el albacea representa todas las ejecuciones pendientes de la tarea. Por cierto, notarás que el schedule El método toma un argumento de llamado como argumento (que puede resultar en algo), mientras que el sceduleAtFixedRate El método solo requiere un argumento de ejecución (que devuelve nulo, por lo tanto, no puede devolver nada).

Entonces, si desea imprimir el resultado de cada ejecución, simplemente haga que la tarea en sí misma (la runnable) imprima su resultado, o haga que Runnable ponga su resultado en una cola de bloqueo y tenga el hilo principal take de la cola. Por lo tanto, el hilo principal se bloqueará en el resultado que se coloca algún resultado en la cola.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top