172

How to set a Timer, say for 2 minutes, to try to connect to a Database then throw exception if there is any issue in connection?

Ankita
  • 1,813
  • 2
  • 17
  • 16
  • 1
    Coul the OP clarify if they desire to simple attempt the action for at least 2 minutes, or if the exception must be thrown now later the two minutes, even if an attempt to connect is currently under way – thecoshman Jan 15 '13 at 07:21

5 Answers5

310

So the first part of the answer is how to do what the subject asks as this was how I initially interpreted it and a few people seemed to find helpful. The question was since clarified and I've extended the answer to address that.

Setting a timer

First you need to create a Timer (I'm using the java.util version here):

import java.util.Timer;

..

Timer timer = new Timer();

To run the task once you would do:

timer.schedule(new TimerTask() {
  @Override
  public void run() {
    // Your database code here
  }
}, 2*60*1000);
// Since Java-8
timer.schedule(() -> /* your database code here */, 2*60*1000);

To have the task repeat after the duration you would do:

timer.scheduleAtFixedRate(new TimerTask() {
  @Override
  public void run() {
    // Your database code here
  }
}, 2*60*1000, 2*60*1000);

// Since Java-8
timer.scheduleAtFixedRate(() -> /* your database code here */, 2*60*1000, 2*60*1000);

Making a task timeout

To specifically do what the clarified question asks, that is attempting to perform a task for a given period of time, you could do the following:

ExecutorService service = Executors.newSingleThreadExecutor();

try {
    Runnable r = new Runnable() {
        @Override
        public void run() {
            // Database task
        }
    };

    Future<?> f = service.submit(r);

    f.get(2, TimeUnit.MINUTES);     // attempt the task for two minutes
}
catch (final InterruptedException e) {
    // The thread was interrupted during sleep, wait or join
}
catch (final TimeoutException e) {
    // Took too long!
}
catch (final ExecutionException e) {
    // An exception from within the Runnable task
}
finally {
    service.shutdown();
}

This will execute normally with exceptions if the task completes within 2 minutes. If it runs longer than that, the TimeoutException will be throw.

One issue is that although you'll get a TimeoutException after the two minutes, the task will actually continue to run, although presumably a database or network connection will eventually time out and throw an exception in the thread. But be aware it could consume resources until that happens.

Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
andrewmu
  • 14,276
  • 4
  • 39
  • 37
  • Oh I guess you got my problem wrong, I have to repeatedly try to to connect to database till 2 minutes everytime – Ankita Oct 29 '10 at 08:28
  • I am sorry but my requirement is that I want to give 2 minutes to connect to the database and then it will just throw some error message.It is like I want to set a time limit to try to connect to the database – Ankita Oct 29 '10 at 13:10
  • 8
    READERS BEWARE: This answer is blatantly wrong. It sets a timer to wait 2 minutes, and then run a DB query after that 2 minute delay, and then it runs it again and again every 2 minutes. What it does NOT do is to run the DB query right away, and then fail out after 2 minutes which is what I think the question asked for (as clarified in the comment). – AgilePro Feb 14 '13 at 07:23
  • 2
    @AgilePro That was true. I didn't answer the question as it was eventually stated and I've now updated it to address that. – andrewmu Feb 23 '13 at 20:29
  • `Timer timer = new Timer();` - no such method in `Timer` class.. Java 1.7 – Ernestas Gruodis Sep 01 '13 at 18:03
  • 1
    @ErnestasGruodis The core APIs list the constructor as public: http://docs.oracle.com/javase/7/docs/api/java/util/Timer.html#Timer() You might have a different Timer class in your classpath - try java.util.Timer as the class. – andrewmu Sep 02 '13 at 16:50
  • It would be nice to specify which package timer we are using. There are at least 4 Timer in Java 1.7. – user1633277 Oct 31 '13 at 14:00
  • @andrewmu This only connects to one server(first one0. How can you do this for every server in the list? – JayC Jun 16 '17 at 18:06
  • This doesn't seem to work although i really wish it did: // Since Java-8 timer.schedule(() -> /* your database code here */, 2*60*1000); – markthegrea Dec 04 '19 at 15:51
  • 4
    How you use timer.schedule() with lambda expression (since java 8)? TimerTask(first parameter) isn't even functional interface. TimerTask just an abstract class. – User8500049 May 26 '20 at 12:55
  • 3
    TimerTask is not a functional interface! https://stackoverflow.com/questions/37970682/passing-lambda-to-a-timer-instead-of-timertask – Tharindu Sathischandra Sep 11 '20 at 07:44
27

Use this

long startTime = System.currentTimeMillis();
long elapsedTime = 0L.

while (elapsedTime < 2*60*1000) {
    //perform db poll/check
    elapsedTime = (new Date()).getTime() - startTime;
}

//Throw your exception
nimWM
  • 367
  • 3
  • 2
  • 1
    hmm... this would technically work, except it does not cover edge cases, where you the time runs out AS you are performing a DB poll, which may be required by the OP – thecoshman Oct 11 '12 at 10:06
  • 1
    This is the only correct answer. It will run on a single thread, and will calculate the end time without drift. Using a TimerTask is exactly the wrong thing to do in this case. I a surprised at how many examples on StackOverflow suggest this same sort of wrong headed thing. – AgilePro Jan 14 '13 at 18:22
  • 1
    @thecoshman - the timer implementations do NOT interrupt the DB operation once it is in progress, nor does this. In any case, you can only control the time that you start the DB operation. There is a common misconception that you need a "timer" in order to time things, but you don't. You need only to DO something, and by using the current time make sure you don't DO IT too long. – AgilePro Jan 14 '13 at 18:35
  • let's say you have to either return the connection or throw after EXACTLY two minutes, this will not work. it will if AFTER two minutes of trying to connect you have still failed to connect. In a situation where the connection check takes say two weeks, this will take that long to throw an exception. – thecoshman Jan 14 '13 at 23:47
  • Partially correct: If your scenario is to pop up a warning dialog after exactly 2 minutes, then you are correct, you want a timer that will do the work of popping up the window. But note in that case you MUST NOT do the DB access on that timer thread, or you would have the same problem that you have here -- the DB operation would still have to complete. The timer does NOT interrupt the actual DB operation. The question was not to produce a UI event exactly two minutes later, but instead to poll the DB and stop polling after two minutes. Given that question, this implementation is optimal. – AgilePro Jan 15 '13 at 04:00
  • Actually, I don't see the question saying exactly how it wants to work. I would normally assume that an approach like this is the desired approach, where an action is attempted for a given a time. The more restrictive scenario I give, where by you need to throw an exception exactly no later then the time limit is a more complex one, and yes, would require threading to some degree. It also has problems of what to do with the thread that is currently stuck trying to connect to the DB, and how get a flawless timer. I could be wrong, but if you 'sleep' for x seconds, you sleep for at least that... – thecoshman Jan 15 '13 at 07:17
  • I think this is a common problem with most languages though, when you sleep you simply request that you do not wake up for at least that long. Of course you might be resumed sooner if something happens, you might not be resumed for a lot longer. – thecoshman Jan 15 '13 at 07:19
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/22768/discussion-between-burnt-too-many-times-and-thecoshman) – AgilePro Jan 15 '13 at 16:38
  • 20
    This is actually very bad coding style, since the while loop constantly runs and checks for stuff... bad for the cpu and bad for the battery life time. – Infinite Jul 02 '13 at 18:49
  • +1 for `System.currentTimeMillis();` It has been very userful in mycase with an if before a thread's `wait(milliseconds)` – simoconfa Jun 16 '18 at 23:24
  • @nimWM This answer uses the Date class. Unfortunately, Item 50 of Effective Java by Joshua Bloch says, "Date is obsolete and should no longer be used in new code." – Brian Schack Dec 30 '20 at 20:45
12

Ok, I think I understand your problem now. You can use a Future to try to do something and then timeout after a bit if nothing has happened.

E.g.:

FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
  @Override
  public Void call() throws Exception {
    // Do DB stuff
    return null;
  }
});

Executor executor = Executors.newSingleThreadScheduledExecutor();
executor.execute(task);

try {
  task.get(5, TimeUnit.SECONDS);
}
catch(Exception ex) {
  // Handle your exception
}
andrewmu
  • 14,276
  • 4
  • 39
  • 37
  • Exception is thrown but the program is not getting terminated.Please help me through this. – Ankita Nov 02 '10 at 13:22
  • 2
    You can use ExecutorService class instead of Executor. It has shutdown() method to stop the executor. – Rites Nov 02 '10 at 13:35
  • 1
    Executors will swallow thrown exceptions that you don't specifically handle in your Callable/Runnable. If your Runnable/Callable doesn't catch and handle the exception itself and it is provided to you vs you owning it, then you need to subclass the ScheduledExecutorService and override afterExecute (make sure to call super.afterExecute()). The second argument to afterExecute will be the throwable from the Runnable/Callable – adam Mar 28 '12 at 21:30
4
    new java.util.Timer().schedule(new TimerTask(){
        @Override
        public void run() {
            System.out.println("Executed...");
           //your code here 
           //1000*5=5000 mlsec. i.e. 5 seconds. u can change accordngly 
        }
    },1000*5,1000*5); 
Mahadev Mane
  • 810
  • 8
  • 11
  • just copy pest above code it will work fine. I have given two times 'time' first is for first time to execute this code and second is for interval time. – Mahadev Mane May 06 '17 at 13:16
  • 2
    The documentation for Timer recommends using the Executor framework instead. https://docs.oracle.com/javase/10/docs/api/java/util/Timer.html – Karan Khanna Nov 02 '18 at 13:04
4

[Android] if someone looking to implement timer on android using java.

you need use UI thread like this to perform operations.

Timer timer = new Timer();
timer.schedule(new TimerTask() {
           @Override
            public void run() {
                ActivityName.this.runOnUiThread(new Runnable(){
                    @Override
                      public void run() {
                       // do something
                      }        
                });
            }
        }, 2000));
Abhishek Garg
  • 3,092
  • 26
  • 30