【问题标题】:Using a ScheduledExecutorService to run a task on a periodic basis in Java在 Java 中使用 ScheduledExecutorService 定期运行任务
【发布时间】:2019-01-01 00:00:04
【问题描述】:

我正在开发一个程序,该程序将从数据源读取数据,并在读取数据时发布该数据。我有一个读取器和一个写入器,读取器产生几个线程来读取它需要读取的所有数据,将数据放入队列中,写入器从队列中读取数据并发布它。

我有一个控制器供读者使用,也有一个控制器供作者使用。控制器实现了Callable 接口,但可以实现Runnable 接口,因为我的调用返回是Void

我想使用一个执行器来运行两个控制器。读取器控制器需要每 X 分钟调用一次(并且 X 大于控制器运行所需的时间)。

现在,我正在创建一个Callables 列表,将它们发送到一个 ExecutorService,即:

List<Future<Void>> futures = ExecutorService es = new Executors.newFixedThreadPoll(2);
for(Future<Void> future: futures) {
    try {
        future.get();
    } catch (Exception e) {
        // log the error
    }
}

我怎样才能把它变成一个调度执行器,每 30 分钟(或更准确地说,在最后一个作业运行后 30 分钟)运行一次可调用对象?

【问题讨论】:

  • 你在使用任何 spring 库吗?
  • @Deadpool No. Guice
  • 我想知道反应式编程模型和工具是否适合您的需求。

标签: java executorservice java-threads


【解决方案1】:

好的,您可以通过多种方式进行操作。但如果性能是重要,您可以像这样在自己的线程中处理这些事情:

public class TaskTimer extends Thread {

private java.util.concurrent.LinkedBlockingQueue<Runnable> taskQueue;
private int timeToWait;
private Long lastTime = -1l;

public TaskTimer(int time)
{
    if(time<0)
        throw new IllegalStateException("time can not negative");

    timeToWait = time;
    taskQueue = new java.util.concurrent.LinkedBlockingQueue<>();
}


void  scheduleTask(Runnable task) throws InterruptedException {
    taskQueue.put(task);
}

boolean  tryScheduleTask(Runnable task) {
    return taskQueue.add(task);
}

@Override
public void run() {

    while (true)
    {
        try {
            Runnable a = taskQueue.take();
            if(!(lastTime==-1 || System.currentTimeMillis()-lastTime>timeToWait))
            {
                //so wait !
                synchronized (lastTime)
                {
                    lastTime.wait(timeToWait-(System.currentTimeMillis()-lastTime));
                }

            }
            try{
                a.run();
                lastTime = System.currentTimeMillis();
            }catch (Throwable e)
            {
                //todo handle e
            }
        } catch (InterruptedException e) {

            break;
        }

    }

}
}

你也可以这样使用它:

TaskTimer t = new TaskTimer(2000);
    t.start();
    t.scheduleTask(new Runnable() {
        @Override
        public void run() {
            System.out.println("1");
        }
    });

    t.tryScheduleTask(new Runnable() {
        @Override
        public void run() {
            System.out.println("2");
        }
    });

希望能帮到你!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-18
    • 1970-01-01
    • 2013-12-21
    • 1970-01-01
    相关资源
    最近更新 更多