6

I have a program where I am able to insert a filepath and it's corresponding parameters to a table.

After that, I have another function called do_Scan() that scans the table and do some processing and indexing to it.

However, I want this function do_Scan() to be run at certain intervals, say every N minutes then it will call this function. The N is definitely configurable.

I was thinking of using a timer class but not quite sure how to implement the configuration. The idea is I create a Timer function that will call the do_Scan method.

The class should be something like this:

public void schedule(TimerTask task,long delay,long period){

}

My main method:

public static void main(String[] args) throws Exception {

    Indexing test= new Indexing();
    java.sql.Timestamp date = new java.sql.Timestamp(new java.util.Date().getTime());
    // Exception e=e.printStackTrace();
    Scanner scanner = new Scanner(System.in);
    System.out.print("Enter a file path: ");
    System.out.flush();
    String filename = scanner.nextLine();
    File file = new File(filename);
    if(file.exists() && !file.isDirectory()) {
        test.index_request(filename,"Active",date,date,"");
    }else{
        test.index_request(filename,"Error",date,date,"Some errorCode");
    }

    // Call schedule() function 
}}

How do I setup the Timer class so it runs indefinitely for certain interval?

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
Daredevil
  • 1,672
  • 3
  • 18
  • 47

5 Answers5

3

The simplest way is using a class which is a part of standard library.

java.util.Timer

Here is a simple example of using it:

import java.util.Timer; 
import java.util.TimerTask; 

class MyTask extends TimerTask 
{ 
   public static int i = 0; 
   public void run() 
   { 
      System.out.println("Hello, I'm timer, running iteration: " + ++i); 
   } 
} 

public class Test 
{ 
   public static void main(String[] args) 
   { 

      Timer timer = new Timer(); 
      TimerTask task = new MyTask(); 

      timer.schedule(task, 2000, 5000);  // 2000 - delay (can set to 0 for immediate execution), 5000 is a frequency.

   } 
} 
Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
  • What about if there is any error occur in there, then I need to write another function to handle it. – Daredevil Nov 28 '18 at 06:50
  • Yes, sure, but it's your custom logic and depends on the application. Timer only gives an ability to run something periodically. It doesn't save you from handling errors – Mark Bramnik Nov 28 '18 at 12:02
3

You can achieve this by using ScheduledThreadPoolExecutor:

Let's assume you have a task method:

public void task(String foo, Integer bar){
    // ...
}

Before Java 1.8

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
executor.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        task(fooParam, barParam);  
    }
}, 0, 60, TimeUnit.SECONDS);

Java 1.8+

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.scheduleAtFixedRate(() -> task(fooParam, barParam), 0, 60, TimeUnit.SECONDS);
ETO
  • 6,970
  • 1
  • 20
  • 37
0

To do that I recommend you to use Java's ScheduledExecutorService which provides you with an API to schedule tasks at fixed rate (among other APIs).

You have 2 options to do that:

  1. Implementing Runnable or Callable (or the like) in your task and call the schedule() method:

    public class IndexingTask implements Runnable {
    
        @Override
        public void run() {
            schedule();
        }
    
        private void schedule() {
            //do something
        }
    }
    
    
    
    public static void main(String[] args) {
        //do some stuff
        long delay = getDelay();
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
        scheduledThreadPool.scheduleAtFixedRate(new IndexingTask(), 0, delay, TimeUnit.SECONDS);
    }
    
  2. Using Lambda expression to do that inline:

    public static void main(String[] args) {
        //do some stuff
        long delay = getDelay();
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
        scheduledThreadPool.scheduleAtFixedRate(() -> doSomething(), 0, delay, TimeUnit.SECONDS);
    }
    

If you're using Spring Framework, you can simply use the @Scheduled annotation as follows:

@Scheduled(fixedRate = 5000)
public void schedule() {
    //do something
}
akauppi
  • 17,018
  • 15
  • 95
  • 120
zuckermanori
  • 1,675
  • 5
  • 22
  • 31
0

There're many ways to solve this issue. I think that the simpliest way, when you use this approach in given place only and do not use external frameworks like Spring:

private void runWithInterval(long millis) {
    Runnable task = () -> {
        try {
            while (true) {
                Thread.sleep(millis);
                // payload
            }
        } catch(InterruptedException e) {
        }
    };

    Thread thread = new Thread(task);
    thread.setDaemon(true);
    thread.start();
}

To call it with 1 minute interval:

runWithInterval(TimeUnit.MINUTES.toMillis(1));

P.S.

Another ways details you can see in other posts here:

  • @Scheduler annotation when using Spring
  • Using thread pool with single thread: ScheduledExecutorService scheduledThreadPool = Executors.newFixedThreadPool(1)
  • Using Timer: new Timer().schedule(new Runnable() {}, TimeUnit.MINUTES.toMillis(1))
akauppi
  • 17,018
  • 15
  • 95
  • 120
Oleg Cherednik
  • 17,377
  • 4
  • 21
  • 35
0

If you are familiar with ReactiveX there is java library called RxJava which can be used as:

Flowable.interval(1, TimeUnit.SECONDS) // Or any other desired interval
        .subscribe(iteration -> System.out.println("Hello, I'm timer, running iteration: " + iteration));

But you really should read more about this approach and library

Tal Ohana
  • 1,128
  • 8
  • 15