33

I have called a method in ServletContextListener as thread ..Now as per my need i have to delay the thread for 1 minutes and then start executing the method called in the thread but i am not able to do that as i am very new in this...

Here is my code ...

public class Startup implements ServletContextListener {

@Override
public void contextDestroyed(ServletContextEvent sce) {
}

public void contextInitialized(ServletContextEvent sce) {
    // Do your startup work here
    System.out.println("Started....");
    //captureCDRProcess();
    new Thread(new Runnable() {

        @Override
        public void run() {

            captureCDRProcess();
        }
    }).start();

}

Please help me .. Thanks in advance..

Adi
  • 1,395
  • 11
  • 37
  • 61
  • Possible duplicate of [java: run a function after a specific number of seconds](http://stackoverflow.com/questions/2258066/java-run-a-function-after-a-specific-number-of-seconds) – AlikElzin-kilaka Nov 13 '16 at 17:27

5 Answers5

67

To do this properly, you need to use a ScheduledThreadPoolExecutor and use the function schedule like this:

final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(NUM_THREADS);
executor.schedule(new Runnable() {
  @Override
  public void run() {
    captureCDRProcess();
  }
}, 1, TimeUnit.MINUTES);

Thread.sleep is not the way to go, because it does not guarantee that it wakes up after a minute. Depending on the OS and the background tasks, it could be 60 seconds, 62 seconds or 3 hours, while the scheduler above actually uses the correct OS implementation for scheduling and is therefore much more accurate.

In addition this scheduler allows several other flexible ways to schedule tasks like at a fixed rate or fixed delay.

Edit: Same solution using the new Java8 Lamda syntax:

final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(NUM_THREADS);
executor.schedule(() -> captureCDRProcess(), 1, TimeUnit.MINUTES);
TwoThe
  • 13,879
  • 6
  • 30
  • 54
  • 1
    To clarify for other readers, it is that `1` and `TimeUnit.MINUTES` at the end that controls the delay before the new thread is launched. – Basil Bourque Feb 26 '14 at 04:36
  • What is NUM_THREADS here ,,is it an instance? – Shikhar Dec 28 '15 at 07:10
  • @Shikhar - it is `corePoolSize` - the number of threads to keep in the pool, even if they are idle. See https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html – Someone Somewhere Feb 13 '16 at 00:12
  • I like this example: https://www.mkyong.com/java/java-scheduledexecutorservice-examples/ – lepe Sep 19 '19 at 05:18
11

Or you can delay creating the thread with Timer and TimerTask:

public void contextInitialized() {
    // Do your startup work here
    System.out.println("Started....");

    Timer timer = new Timer();

    TimerTask delayedThreadStartTask = new TimerTask() {
        @Override
        public void run() {

            //captureCDRProcess();
            //moved to TimerTask
            new Thread(new Runnable() {
                @Override
                public void run() {

                    captureCDRProcess();
                }
            }).start();
        }
    };

    timer.schedule(delayedThreadStartTask, 60 * 1000); //1 minute
}
Melquiades
  • 8,496
  • 1
  • 31
  • 46
3

Have a look at Thread.sleep(). Maybe add it to the new thread's run method, so that it sleeps the needed time before doing any meaningful work.

Tarmo R
  • 1,123
  • 7
  • 15
2

You can start thread and inside the thread use sleep method for one minute.

Ashish
  • 1,943
  • 2
  • 14
  • 17
Prettygeek
  • 2,461
  • 3
  • 22
  • 44
0

ScheduledThreadPoolExecutor has this ability, but it's quite heavyweight.

Here's a simple implementation with a test (signature close to Android's Handler.postDelayed()):

public class JavaUtil {
    public static void postDelayed(final Runnable runnable, final long delayMillis) {
        final long requested = System.currentTimeMillis();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        long leftToSleep = requested + delayMillis - System.currentTimeMillis();
                        if (leftToSleep > 0) {
                            Thread.sleep(leftToSleep);
                        }
                        break;
                    } catch (InterruptedException ignored) {
                    }
                }
                runnable.run();
            }
        }).start();
    }
}

Test:

@Test
public void testRunsOnlyOnce() throws InterruptedException {
    long delay = 100;
    int num = 0;
    final AtomicInteger numAtomic = new AtomicInteger(num);
    JavaUtil.postDelayed(new Runnable() {
        @Override
        public void run() {
            numAtomic.incrementAndGet();
        }
    }, delay);
    Assert.assertEquals(num, numAtomic.get());
    Thread.sleep(delay + 10);
    Assert.assertEquals(num + 1, numAtomic.get());
    Thread.sleep(delay * 2);
    Assert.assertEquals(num + 1, numAtomic.get());
}
AlikElzin-kilaka
  • 34,335
  • 35
  • 194
  • 277