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.
Uruchomienie tego kodu spowoduje wyciek wątków. Po zakończeniu pamiętaj o wyczyszczeniu timera.
skaffman
1
@skaffman: Dodałem oświadczenie z javadoc. Czy naprawdę musisz posprzątać po rozmowie telefonicznej?
tangens
1
Może być w porządku, ale może nie być. Jeśli uruchomisz ten fragment kodu wiele razy, będziesz mieć luźne wątki bez możliwości ich uporządkowania.
skaffman
5
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.Timerzadania są złe; javax.swing.Timerdziałania dobre).
Tom Hawtin - tackline
2
@PaulAlexander Zgodnie z dokumentacją - wywołanie cancelmetody timera na końcu metody run wyczyściłoby wątek wykonania TimerTasks.
Dandalf
58
Coś takiego:
// When your program starts upScheduledExecutorService executor =Executors.newSingleThreadScheduledExecutor();// then, when you want to schedule a taskRunnable task =....
executor.schedule(task,5,TimeUnit.SECONDS);// and finally, when your program wants to exit
executor.shutdown();
Istnieje wiele innych metod fabrycznych, Executorktó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.
Timer timer =newTimer(3000,newActionListener(){@Overridepublicvoid 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.
new java.util.Timer().schedule(new java.util.TimerTask(){@Overridepublicvoid run(){// your code here, and if you have to refresh UI put this code:
runOnUiThread(newRunnable(){publicvoid 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(){@Overridepublicvoid run(){// your code here// close the thread
t.cancel();}},5000);
Nie powinno Timer tbyć zadeklarowane, finalponieważ jest uzyskiwane wewnątrz klasy wewnętrznej?
Joshua Pinter
1
@JoshuaPinter Tak, powinien być uznany za ostateczny, ale nie musi być jawnie ogłaszany jako ostateczny w przynajmniej Javie 8. Musi być tylko „efektywnie ostateczny” ( javarevisited.blogspot.com/2015/03/… )
Dandalf
4
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.
I to tylko gwarantuje, że wykonanie będzie działać po 4 sekundach, co może oznaczać również po 10 sekundach!
questzen
2
questzen, przekonasz się, że wszystkie opisane tutaj metody to robią. W rzeczywistości, nawet jeśli planujesz coś na poziomie systemu operacyjnego, generalnie możesz zagwarantować tylko minimalny czas, który upłynął przed wydarzeniem.
Ethan
Nie o to chodziło w rzeczywistości
Inder R Singh
Po prostu musiałem oddać temu głos przeciw - wcale nie odpowiadając na zadane pytanie.
Mayer
OP powiedział w komentarzu "Chcę dalej robić coś innego"; ten kod oczywiście nie.
publicclassJavaUtil{publicstaticvoid postDelayed(finalRunnable runnable,finallong delayMillis){finallong requested =System.currentTimeMillis();newThread(newRunnable(){@Overridepublicvoid 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();}}
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;publicclassDelaySample{publicstaticvoid main(String[] args){DelayUtil d =newDelayUtil();System.out.println("started:"+newDate());
d.delay(500);System.out.println("half second after:"+newDate());
d.delay(1,TimeUnit.MINUTES);System.out.println("1 minute after:"+newDate());}}
Implementacja DelayUtil
import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.ReentrantLock;publicclassDelayUtil{/**
* 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
*/publicvoid delay(finallong durationInMillis){
delay(durationInMillis,TimeUnit.MILLISECONDS);}/**
* @param duration the time duration in the given {@code sourceUnit}
* @param unit
*/publicvoid delay(finallong duration,finalTimeUnit unit){long currentTime =System.currentTimeMillis();long deadline = currentTime+unit.toMillis(duration);ReentrantLock lock =newReentrantLock();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();}}}
Chociaż ten kod może odpowiedzieć na pytanie, zapewnia dodatkowy kontekst dotyczący tego, dlaczego i / lub jak ten kod odpowiada, poprawia jego długoterminową wartość.
Odpowiedzi:
EDYTOWAĆ:
javadoc mówi:
źródło
import java.util.Timer; import java.util.TimerTask;
może uczynić bardziej oczywistym, że tak nie jestjavax.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:
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.źródło
Przykład użycia
javax.swing.Timer
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.
źródło
Mój kod wygląda następująco:
źródło
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.
źródło
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.
źródło
możesz użyć funkcji Thread.Sleep ()
Twoja funkcja zostanie wykonana po 4 sekundach. Może to jednak spowodować wstrzymanie całego programu ...
źródło
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 ):
Test:
źródło
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.
Implementacja DelayUtil
źródło
źródło