java: belirli bir saniye sonra bir işlevi çalıştırır


148

5 saniye sonra yürütülmesini istediğim belirli bir işlevim var. Java ile nasıl yapabilirim?

Javax.swing.timer buldum, ancak nasıl kullanılacağını gerçekten anlayamıyorum. Görünüşe göre bu sınıfın sağladığı daha basit bir şey arıyorum.

Lütfen basit bir kullanım örneği ekleyin.


5 saniye bekleyip bir şey yürütmek mi istiyorsunuz yoksa 5 saniye içinde başka bir şey yapmaya devam etmek istiyor musunuz?
whiskysierra

başka bir şey yapmaya devam etmek istiyorum
ufk

Yanıtlar:


229
new java.util.Timer().schedule( 
        new java.util.TimerTask() {
            @Override
            public void run() {
                // your code here
            }
        }, 
        5000 
);

DÜZENLE:

javadoc diyor ki:

Bir Timer nesnesine son canlı başvuru ortadan kalktıktan ve tüm bekleyen görevler yürütmeyi tamamladıktan sonra, zamanlayıcının görev yürütme iş parçacığı zarif bir şekilde sonlanır (ve çöp toplama işlemine tabi tutulur). Ancak, bu işlemin gelişmesi uzun sürebilir.


1
Bu kodu çalıştırırsanız, konuları sızdırırsınız. İşiniz bittiğinde zamanlayıcıyı temizlediğinizden emin olun.
skaffman

1
@skaffman: Javadoc'tan bir açıklama ekledim. Arama programını yaptıktan sonra gerçekten temizlemeniz gerekiyor mu?
tangens

1
Tamam olabilir, ama sonra olmayabilir. Bu kod parçasını birden çok kez çalıştırırsanız, bunları toplamanın hiçbir yolu olmadan tekmeleyen gevşek iş parçacıklarınız olacaktır.
skaffman

5
import java.util.Timer; import java.util.TimerTask;bunun daha açık olmasını sağlayabilir javax.swing.Timer. / Not, Swing (ve aslında AWT) kullanıyorsanız, Event Dispatch Thread (EDT) iş parçacıklarındaki bileşenleri değiştirmek için hiçbir şey yapmamalısınız ( java.util.Timergörevler kötü; javax.swing.Timerişlemler iyi).
Tom Hawtin - tackline

2
@PaulAlexander Dokümanlara göre - cancelrun yönteminin sonunda timer yönteminin çağrılması , TimerTasks'ın yürütme iş parçacığını temizler.
Dandalf

58

Bunun gibi bir şey:

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

ExecutorHavuzda daha fazla iş parçacığı istiyorsanız, bunun yerine kullanabileceğiniz çeşitli diğer fabrika yöntemleri vardır .

Ve unutmayın, işiniz bittiğinde yürütücüyü kapatmanız önemlidir. shutdown()Yöntem son görev tamamlandığında temiz bir şekilde iş parçacığı havuzu kapanacak ve bu gerçekleşene kadar engeller. shutdownNow()iş parçacığı havuzunu derhal sonlandıracaktır.


24

Kullanım örneği 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!

Bu kod yalnızca bir kez yürütülür ve yürütme 3000 ms'de (3 saniye) gerçekleşir.

Camickr'den bahsedildiği gibi, kısa bir giriş için " Swing Zamanlayıcıları Nasıl Kullanılır " araması yapmalısınız .


6

Kodum aşağıdaki gibidir:

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

5

@Tangens cevabının bir çeşidi olarak: çöp toplayıcının iş parçacığını temizlemesini bekleyemiyorsanız, çalıştırma yönteminizin sonunda zamanlayıcıyı iptal edin.

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

Bir iç sınıf içinde erişildiği Timer tiçin ilan edilmemeli finalmidir?
Joshua Pinter

1
Evet @JoshuaPinter, nihai beyan edilmelidir ama açıkça Java en az 8. Sadece "etkili bir şekilde nihai" olması gerekir (nihai ilan edilmesi gerekmez javarevisited.blogspot.com/2015/03/... )
Dandalf

4

Asıl sorunuz "Salınım Zamanlayıcısı" ndan bahsediyor. Aslında sorunuz SWing ile ilgili ise, util.Timer DEĞİL Swing Zamanlayıcı kullanmanız gerekir.

Daha fazla bilgi için " Zamanlayıcıların Kullanımı " konulu Swing eğitimindeki bölümü okuyun .


4

Thread.Sleep () işlevini kullanabilirsiniz

Thread.sleep(4000);
myfunction();

İşleviniz 4 saniye sonra yürütülecektir. Ancak bu tüm programı duraklatabilir ...


Ve sadece yürütmenin 4sec'den sonra çalışacağını garanti eder, bu da 10 saniye sonra anlamına gelebilir!
questzen

2
questzen, buradaki tüm yöntemlerin bunu yaptığını göreceksiniz . Aslında, işletim sistemi düzeyinde bir şey planlasanız bile, genellikle yalnızca bir etkinlikten önce geçen minimum süreyi garanti edebilirsiniz.
Ethan

Asıl soru bu değildi
Inder R Singh

Ben sadece bu bir aşağıya vermek zorunda kaldı - eldeki soruya hiç cevap değil.
theMayer

OP yorumda "ben başka bir şey yapmaya devam etmek istiyorum" dedi; bu kod açıkçası değil.
Abhijit Sarkar

3

ScheduledThreadPoolExecutor bu yeteneğe sahip, ancak oldukça ağır.

Timer aynı zamanda bu yeteneğe sahiptir ancak sadece bir kez kullanılsa bile birkaç iş parçacığı açar.

İşte bir test ile basit bir uygulama (Android Handler.postDelayed () yakın imzası ):

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

Ölçek:

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

bir döngü denilen uyarı uyku verir
shareef

whileSadece kesinti göz ardı etmektir.
AlikElzin-kilaka

2

Diğer tüm isteksizlerin kodunuzu yeni bir iş parçacığında çalıştırması gerekir. Bazı basit kullanım durumlarında, biraz beklemek ve aynı iş parçacığı / akışı içinde yürütmeye devam etmek isteyebilirsiniz.

Aşağıdaki kod bu tekniği göstermektedir. Unutmayın bu java.util.Timer kaputun altında ne yapar, ancak daha hafif.

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

Uygulamaya Kadar Gecikme

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

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

2
Bu kod soruyu cevaplayabilirken, bu kodun soruyu neden ve / veya nasıl cevapladığı konusunda ek bağlam sağlamak uzun vadeli değerini arttırır.
Mateus
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.