Java: запустить функцию через определенное количество секунд
У меня есть определенная функция, которую я хочу выполнить через 5 секунд.
Как я могу сделать это на Java?
Я нашел javax.swing.timer, но я не могу понять, как его использовать. Похоже, я ищу что-то более простое, чем этот класс.
Добавьте простой пример использования.
Ответы
Ответ 1
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
public void run() {
// your code here
}
},
5000
);
EDIT:
javadoc говорит:
После того, как последняя живая ссылка на объект Timer исчезнет, и все невыполнимые задачи завершены, поток выполнения задачи таймера заканчивается изящно (и становится объектом сбора мусора). Однако это может занять некоторое время.
Ответ 2
Что-то вроде этого:
// When your program starts up
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
// then, when you want to schedule a task
Runnable task = ....
executor.schedule(task, 5, TimeUnit.SECONDS);
// and finally, when your program wants to exit
executor.shutdown();
На Executor
существуют другие методы factory, которые вы можете использовать вместо этого, если вам нужно больше потоков в пуле.
И помните, что важно завершить работу исполнителя, когда вы закончите. Метод shutdown()
очистит пул потоков, когда завершится последняя задача, и будет блокироваться до тех пор, пока это не произойдет. shutdownNow()
немедленно завершит пул потоков.
Ответ 3
Пример использования javax.swing.Timer
Timer timer = new Timer(3000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
// Code to be executed
}
});
timer.setRepeats(false); // Only execute once
timer.start(); // Go go go!
Этот код будет выполняться только один раз, а выполнение происходит в 3000 мс (3 секунды).
Как упоминает camickr, вы должны найти "Как использовать таймеры поворота" для краткого введения.
Ответ 4
вы можете использовать функцию Thread.Sleep()
Thread.sleep(4000);
myfunction();
Ваша функция будет выполняться через 4 секунды. Однако это может приостановить всю программу...
Ответ 5
Мой код выглядит следующим образом:
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
public void run() {
// your code here, and if you have to refresh UI put this code:
runOnUiThread(new Runnable() {
public void run() {
//your code
}
});
}
},
5000
);
Ответ 6
В исходном вопросе упоминается "Таймер качания". Если на самом деле ваш вопрос связан с SWing, тогда вы должны использовать таймер Swing и NOT util.Timer.
Прочтите раздел из руководства Swing по Как использовать таймеры" для получения дополнительной информации.
Ответ 7
Как вариант ответа @tangens: если вы не можете дождаться, когда сборщик мусора очистит ваш поток, отмените таймер в конце вашего метода run.
Timer t = new java.util.Timer();
t.schedule(
new java.util.TimerTask() {
@Override
public void run() {
// your code here
// close the thread
t.cancel();
}
},
5000
);
Ответ 8
ScheduledThreadPoolExecutor
имеет эту способность, но это довольно тяжеловес.
Timer
также обладает этой способностью, но открывает несколько потоков, даже если используется только один раз.
Здесь простая реализация с тестом (подпись, близкая к 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());
}
Ответ 9
public static Timer t;
public synchronized void startPollingTimer() {
if (t == null) {
TimerTask task = new TimerTask() {
@Override
public void run() {
//Do your work
}
};
t = new Timer();
t.scheduleAtFixedRate(task, 0, 1000);
}
}
Ответ 10
Все остальные ответы требуют запуска вашего кода в новом потоке. В некоторых простых случаях вы можете просто подождать немного и продолжить выполнение в том же потоке/потоке.
Код ниже демонстрирует эту технику. Имейте в виду, что это похоже на то, что java.util.Timer делает под капотом, но более легкий.
import java.util.concurrent.TimeUnit;
public class DelaySample {
public static void main(String[] args) {
DelayUtil d = new DelayUtil();
System.out.println("started:"+ new Date());
d.delay(500);
System.out.println("half second after:"+ new Date());
d.delay(1, TimeUnit.MINUTES);
System.out.println("1 minute after:"+ new Date());
}
}
Реализация DelayUtil
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class DelayUtil {
/**
* Delays the current thread execution.
* The thread loses ownership of any monitors.
* Quits immediately if the thread is interrupted
*
* @param duration the time duration in milliseconds
*/
public void delay(final long durationInMillis) {
delay(durationInMillis, TimeUnit.MILLISECONDS);
}
/**
* @param duration the time duration in the given {@code sourceUnit}
* @param unit
*/
public void delay(final long duration, final TimeUnit unit) {
long currentTime = System.currentTimeMillis();
long deadline = currentTime+unit.toMillis(duration);
ReentrantLock lock = new ReentrantLock();
Condition waitCondition = lock.newCondition();
while ((deadline-currentTime)>0) {
try {
lock.lockInterruptibly();
waitCondition.await(deadline-currentTime, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
} finally {
lock.unlock();
}
currentTime = System.currentTimeMillis();
}
}
}