Mam określoną funkcję, którą chcę wykonać po 5 sekundach. Jak mogę to zrobić w Javie?
Znalazłem javax.swing.timer, ale naprawdę nie rozumiem, jak go używać. Wygląda na to, że szukam czegoś prostszego niż ta klasa.
Dodaj prosty przykład użycia.
Mam określoną funkcję, którą chcę wykonać po 5 sekundach. Jak mogę to zrobić w Javie?
Znalazłem javax.swing.timer, ale naprawdę nie rozumiem, jak go używać. Wygląda na to, że szukam czegoś prostszego niż ta klasa.
Dodaj prosty przykład użycia.
Odpowiedzi:
new java.util.Timer().schedule(
new java.util.TimerTask() {
@Override
public void run() {
// your code here
}
},
5000
);
EDYTOWAĆ:
javadoc mówi:
Po zniknięciu ostatniego odniesienia na żywo do obiektu Timer i zakończeniu wykonywania wszystkich zaległych zadań wątek wykonania zadania czasomierza kończy się wdzięcznie (i podlega wyrzucaniu elementów bezużytecznych). Jednak może to zająć dowolnie długi czas.
import java.util.Timer; import java.util.TimerTask;
może uczynić bardziej oczywistym, że tak nie jest javax.swing.Timer
. / Uwaga, jeśli używasz Swinga (a właściwie AWT), nie powinieneś robić nic w celu zmiany komponentów w wątkach niezwiązanych z wysyłaniem zdarzeń (EDT) ( java.util.Timer
zadania są złe; javax.swing.Timer
działania dobre).
cancel
metody timera na końcu metody run wyczyściłoby wątek wykonania TimerTasks.
Coś takiego:
// 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();
Istnieje wiele innych metod fabrycznych, Executor
których możesz użyć zamiast tego, jeśli chcesz mieć więcej wątków w puli.
I pamiętaj, ważne jest, aby zamknąć executor po zakończeniu. shutdown()
Metoda czysto zamknąć puli wątków, gdy ostatnie zadanie jest zakończone i będzie blokować aż tak się dzieje. shutdownNow()
natychmiast zakończy pulę wątków.
Przykład użycia 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!
Ten kod zostanie wykonany tylko raz, a wykonanie zajmie 3000 ms (3 sekundy).
Jak wspomina Camickr, powinieneś sprawdzić „ Jak używać zegarów Swing ”, aby uzyskać krótkie wprowadzenie.
Mój kod wygląda następująco:
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
);
Jako odmiana @tangens odpowiedź: jeśli nie możesz czekać, aż moduł odśmiecania pamięci wyczyści twój wątek, anuluj licznik czasu na końcu metody uruchamiania.
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
);
Timer t
być zadeklarowane, final
ponieważ jest uzyskiwane wewnątrz klasy wewnętrznej?
Twoje pierwotne pytanie dotyczy „Swing Timer”. Jeśli w rzeczywistości twoje pytanie dotyczy SWing, powinieneś używać Swing Timer, a NIE util.Timer.
Przeczytaj sekcję z samouczka Swing na temat „ Jak używać timerów ”, aby uzyskać więcej informacji.
możesz użyć funkcji Thread.Sleep ()
Thread.sleep(4000);
myfunction();
Twoja funkcja zostanie wykonana po 4 sekundach. Może to jednak spowodować wstrzymanie całego programu ...
ScheduledThreadPoolExecutor
ma tę umiejętność, ale jest dość ciężki.
Timer
ma również tę zdolność, ale otwiera kilka wątków, nawet jeśli zostanie użyty tylko raz.
Oto prosta implementacja z testem (sygnatura zbliżona do Handler.postDelayed () systemu Android ):
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() {
// The while is just to ignore interruption.
while (true) {
try {
long leftToSleep = requested + delayMillis - System.currentTimeMillis();
if (leftToSleep > 0) {
Thread.sleep(leftToSleep);
}
break;
} catch (InterruptedException ignored) {
}
}
runnable.run();
}
}).start();
}
}
Test:
@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());
}
while
to na celu zignorowanie przerw.
Wszystkie inne odpowiedzi wymagają uruchomienia kodu w nowym wątku. W niektórych prostych przypadkach możesz po prostu trochę poczekać i kontynuować wykonywanie w tym samym wątku / przepływie.
Poniższy kod demonstruje tę technikę. Należy pamiętać, że jest to podobne do tego, co java.util.Timer robi pod maską, ale jest lżejsze.
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());
}
}
Implementacja 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();
}
}
}
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);
}
}