如何在ScheduledThreadPoolExecutor的afterExecute中从任务获取数据

时间:2014-03-03 11:18:00

标签: java scheduledexecutorservice

我正在使用ScheduledThreadPoolExecutor而且我不太热衷于处理某些事情。

我正在以这种方式安排一些任务:

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

act是一个Runnable类,它通过参数:

返回一些数据
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;
}
}

现在在ExtendedSecheduledExecutor的afterExecute方法中,我想获取任务TareaActualizacion的对象Instalacion,但我不知道该怎么做。 我的ExtendedScheduledExecutor类看起来像这样:

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??
}

}

我怎么解决呢?

谢谢!

诺伊斯

2 个答案:

答案 0 :(得分:1)

正如Stephan已经在https://stackoverflow.com/a/22145530中指出的那样,你应该尝试将调度和执行与通知分离。

这样做的一种方法是将实际任务(TareaActualizacion)包装到仅执行实际任务的Runnable接口的另一个实现中,然后通知回调有关已执行的任务执行。

根据您的具体要求,实施可能有几个自由度,但一般方法可能大致如下:

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;
        }
    }
}

答案 1 :(得分:0)

这是一种海湾方式。你不应该试图从Executor中获取结果,因为它只负责调度和执行任务,而不是发生在它们内部的任何事情。

您的TareaActualizacion runnable应该将结果发布到您需要的另一段代码中。这可以使用队列或最简单的SwingUtilities.invokeLater()来实现。