30

我已经在 ServletContextListener 中调用了一个方法作为线程..现在根据我的需要,我必须将线程延迟 1 分钟,然后开始执行线程中调用的方法,但我不能这样做,因为我在这方面很新...

这是我的代码...

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();

}

请帮助我..提前谢谢..

4

5 回答 5

59

要正确执行此操作,您需要使用 ScheduledThreadPoolExecutor 并使用函数schedule,如下所示:

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

Thread.sleep不是要走的路,因为它不能保证它在一分钟后醒来。根据操作系统和后台任务,它可能是 60 秒、62 秒或 3 小时,而上面的调度程序实际上使用正确的操作系统实现进行调度,因此更加准确。

此外,此调度程序还允许使用其他几种灵活的方式来安排任务,例如以固定速率或固定延迟。

编辑:使用新的 Java8 Lamda 语法的相同解决方案:

final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(NUM_THREADS);
executor.schedule(() -> captureCDRProcess(), 1, TimeUnit.MINUTES);
于 2013-11-15T11:09:36.757 回答
11

或者您可以使用 Timer 和 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
}
于 2013-11-15T10:58:40.453 回答
3

看看Thread.sleep()。也许将它添加到新线程的 run 方法中,以便它在做任何有意义的工作之前休眠所需的时间。

于 2013-11-15T10:48:22.650 回答
2

你可以启动thread和里面的线程使用sleep方法一分钟。

于 2013-11-15T10:47:58.050 回答
0

ScheduledThreadPoolExecutor有这个能力,但是相当的重量级。

这是一个带有测试的简单实现(签名接近 Android 的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
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());
}
于 2016-11-13T17:26:20.543 回答