Подтвердить что ты не робот

Как начать поток после указанной задержки времени в java

Я вызвал метод в 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();

}

Пожалуйста, помогите мне.. Спасибо заранее.

4b9b3361

Ответ 1

Чтобы сделать это правильно, вам нужно использовать 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);

Ответ 2

Или вы можете отложить создание потока с помощью 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
}

Ответ 3

Вы можете запустить thread и внутри потока использовать метод sleep в течение одной минуты.

Ответ 4

Посмотрите Thread.sleep(). Возможно, добавьте его в новый метод запуска потока, чтобы он спал необходимое время, прежде чем выполнять какую-либо значимую работу.

Ответ 5

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