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 は、1 分後に起動することを保証しないため、進むべき道ではありません。OS とバックグラウンド タスクに応じて、60 秒、62 秒、または 3 時間かかる場合がありますが、上記のスケジューラは実際にはスケジューリングに正しい OS 実装を使用しているため、はるかに正確です。

さらに、このスケジューラーは、固定レートや固定遅延など、タスクをスケジュールするための他のいくつかの柔軟な方法を可能にします。

編集:新しい Java8 ラムダ構文を使用した同じソリューション:

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 に答える
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 に答える