Using a ScheduledExecutorService to run a task on a periodic basis in Java

送分小仙女□ 提交于 2021-02-11 15:00:49

问题


I am working on a program that will read data from a data source, and publish that data as it is read. I have a reader and a writer, the reader spawns several threads to read all the data it needs to read, puts the data into a queue, and the writer reads the data from the queue an publishes it.

I have a controller for my readers and a controller for my writers. The controllers implement the Callable interface, but could implement the Runnable interface as my call return is Void.

I want to use an executor to run the two controllers. The reader controller will need to be invoked every X minutes (and X is greater than the time it takes the controller to run).

Right now, I am creating a list of Callables, sending them to an ExecutorService that is:

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

How can I turn this into a scheduling executor that runs the callables every 30 minutes (or more precisely, 30 minutes after the last job ran)?


回答1:


Okay you can do it several ways . but if performance is important you could handle these things in you own thread like this :

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

    }

}
}

and also you can use it like this :

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

hope I could help you !



来源:https://stackoverflow.com/questions/53992215/using-a-scheduledexecutorservice-to-run-a-task-on-a-periodic-basis-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!