Использование ScheduledExecutorService для периодического запуска задачи в Java - PullRequest
0 голосов
/ 01 января 2019

Я работаю над программой, которая будет считывать данные из источника данных и публиковать эти данные по мере их чтения.У меня есть читатель и писатель, читатель создает несколько потоков, чтобы прочитать все данные, которые ему нужны для чтения, помещает данные в очередь, а писатель читает данные из очереди и публикует их.

Iесть контроллер для моих читателей и контроллер для моих писателей.Контроллеры реализуют интерфейс 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 минут после последнего запуска задания)?

1 Ответ

0 голосов
/ 01 января 2019

Хорошо, вы можете сделать это несколькими способами.но если производительность важна , вы можете обрабатывать эти вещи в своем собственном потоке следующим образом:

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

надеюсь, я смогу вам помочь!

...