Question

I'm using ScheduledThreadPoolExecutor and I don't know hot to deal with something.

I'm scheduling some tasks this way:

scheduledExecService = new ExtendedScheduledExecutor(numThreads, myThreadFactory);
TareaActualizacion act = new TareaActualizacion(inst);
ScheduledFuture<?> handle = scheduledExecService.scheduleWithFixedDelay(act, retrasoInicial, segundosRefresco, TimeUnit.SECONDS);

act is a Runnable class that recive some data by parameter:

public class TareaActualizacion implements Runnable {
private Instalacion instalacion;
public TareaActualizacion(Instalacion instalacion) {
    this.instalacion = instalacion;
}
@Override
public void run() {
    //Do something
}
public Instalacion getInstalacion() {
    return instalacion;
}
}

Now in the afterExecute method of the ExtendedSecheduledExecutor I want to get the object Instalacion of the task TareaActualizacion but I don't know how to do it. My ExtendedScheduledExecutor class looks like this:

public class ExtendedScheduledExecutor extends ScheduledThreadPoolExecutor{

public ExtendedScheduledExecutor(int arg0) {
    super(arg0);
}
public ExtendedScheduledExecutor(int arg0, ThreadFactory arg1) {
    super(arg0, arg1);
}

@Override
protected void afterExecute(Runnable r, Throwable t)
{
    super.afterExecute(r, t);

    System.out.println("Executing afterExecute. Throwable is " + t);
    if (t != null)
        t.printStackTrace();
    //I need to get the Instalacion attribute from TareaActualizacion task. How can I do it??
}

}

Any idea of how can I solve it??

Thank you!

Neus

No correct solution

OTHER TIPS

As Stephan already pointed out in https://stackoverflow.com/a/22145530 , you should try to decouple the scheduling and execution from the notification.

One approach for this could be to wrap the actual task (TareaActualizacion) into another implementation of the Runnable interface that only executes the actual task, and afterwards notifies a callback about the task that has been executed.

Depending on your precise requirements, there may be several degrees of freedom for the implementation, but a general approach could roughly look like this:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledTaskNotification
{
    public static void main(String[] args) throws Exception
    {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(4);

        int n = 3;
        for (int i = 0; i < n; i++)
        {
            UpdateTask updateTask = new UpdateTask(i);

            RunnableCallback<UpdateTask> callback = new RunnableCallback<UpdateTask>()
            {
                @Override
                public void runnableFinished(UpdateTask updateTask)
                {
                    System.out.println("Finished "+updateTask+", id "+updateTask.getID());
                }
            };

            Runnable runnableWithCallback =
                createRunnableWithCallback(updateTask, callback);

            executor.scheduleWithFixedDelay(
                runnableWithCallback, 1000, 200+i*200,
                TimeUnit.MILLISECONDS);
        }
    }

    static interface RunnableCallback<T extends Runnable>
    {
        void runnableFinished(T runnable);
    }

    private static <T extends Runnable> Runnable createRunnableWithCallback(
        final T runnable, final RunnableCallback<T> callback)
    {
        return new Runnable()
        {
            @Override
            public void run()
            {
                runnable.run();
                callback.runnableFinished(runnable);
            }
        };
    }

    private static class UpdateTask implements Runnable
    {
        private final int id;

        UpdateTask(int id)
        {
            this.id = id;
        }

        @Override
        public void run()
        {
            System.out.println("Run "+this);
        }

        int getID()
        {
            return id;
        }

        @Override
        public String toString()
        {
            return "UpdateTask "+id;
        }
    }
}

This is a bay way. You should not trying to get the result out of the Executor, because it is only responsible for scheduling and executing tasks, not whats happening inside of them.

Your TareaActualizacion runnable should post the result to another piece of code, where you need it. This can be achieved using a queue or in the easiest case SwingUtilities.invokeLater().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top