Как начать поток после указанной задержки времени в 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();
}
Пожалуйста, помогите мне..
Спасибо заранее.
Ответы
Ответ 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());
}