Java'da Zamanlayıcı nasıl ayarlanır?


152

Bir Veritabanına bağlanmayı denemek ve bağlantıda herhangi bir sorun varsa istisna atmak için 2 dakikalık bir Zamanlayıcı nasıl ayarlanır?


1
OP, eylemi en az 2 dakika boyunca basit bir şekilde denemek isteyip istemediklerini veya şu anda bağlantı kurma girişimi devam ediyor olsa bile istisnanın şimdi iki dakika sonra atılması
gerekip gerekmediğini açıklığa kavuşturun

Yanıtlar:


281

Yani cevabın ilk kısmı, konunun sorduğu şeyi nasıl yapacağımdır, çünkü başlangıçta onu böyle yorumladım ve birkaç kişi yardımcı bulmuş görünüyordu. O zamandan beri soru açıklığa kavuşmuştu ve cevabı bunu ele alacak şekilde genişlettim.

Bir zamanlayıcı ayarlama

Öncelikle bir Zamanlayıcı oluşturmanız gerekir ( java.utilsürümü burada kullanıyorum ):

import java.util.Timer;

..

Timer timer = new Timer();

Görevi bir kez yapmak için şunları yapacaksınız:

timer.schedule(new TimerTask() {
  @Override
  public void run() {
    // Your database code here
  }
}, 2*60*1000);
// Since Java-8
timer.schedule(() -> /* your database code here */, 2*60*1000);

Yapacağınız süreden sonra görevin tekrar etmesini sağlamak için:

timer.scheduleAtFixedRate(new TimerTask() {
  @Override
  public void run() {
    // Your database code here
  }
}, 2*60*1000, 2*60*1000);

// Since Java-8
timer.scheduleAtFixedRate(() -> /* your database code here */, 2*60*1000, 2*60*1000);

Görev zaman aşımına uğruyor

Açıklığa kavuşturulmuş sorunun sorduğu şeyi, yani belirli bir süre için bir görevi yerine getirmeye çalışmayı özellikle yapmak için aşağıdakileri yapabilirsiniz:

ExecutorService service = Executors.newSingleThreadExecutor();

try {
    Runnable r = new Runnable() {
        @Override
        public void run() {
            // Database task
        }
    };

    Future<?> f = service.submit(r);

    f.get(2, TimeUnit.MINUTES);     // attempt the task for two minutes
}
catch (final InterruptedException e) {
    // The thread was interrupted during sleep, wait or join
}
catch (final TimeoutException e) {
    // Took too long!
}
catch (final ExecutionException e) {
    // An exception from within the Runnable task
}
finally {
    service.shutdown();
}

Görev 2 dakika içinde tamamlanırsa bu, istisnalar dışında normal şekilde yürütülür. Bundan daha uzun çalışıyorsa, TimeoutException atılır.

Bir sorun, iki dakikadan sonra bir Zaman Aşımı İstisnası almanıza rağmen, büyük olasılıkla bir veritabanı veya ağ bağlantısı sonunda zaman aşımına uğrayacak ve iş parçacığında bir istisna atacak olsa da , görev gerçekten çalışmaya devam edecek olmasıdır. Ancak, bu gerçekleşene kadar kaynakları tüketebileceğini unutmayın.


Sanırım sorunumu yanlış anladınız, veritabanına her seferinde 2 dakikaya kadar tekrar tekrar bağlanmayı denemeliyim
Ankita

7
OKUYUCULAR DİKKAT: Bu cevap bariz bir şekilde yanlıştır. Bir zamanlayıcıyı 2 dakika beklemeye ayarlar ve ardından bu 2 dakikalık gecikmeden sonra bir DB sorgusu çalıştırır ve ardından her 2 dakikada bir tekrar tekrar çalıştırır. Yapmadığı şey, DB sorgusunu hemen çalıştırmak ve sonra 2 dakika sonra başarısız olmaktır ki bu soruyu sordu (yorumda açıklandığı gibi).
AgilePro

2
@AgilePro Bu doğruydu. Soruya sonunda belirtildiği gibi cevap vermedim ve şimdi bunu ele almak için güncelledim.
andrewmu

1
@ErnestasGruodis Çekirdek API'ler yapıcıyı genel olarak listeler: docs.oracle.com/javase/7/docs/api/java/util/Timer.html#Timer () Sınıf yolunuzda farklı bir Timer sınıfınız olabilir - java'yı deneyin. sınıf olarak util.Timer.
andrewmu

1
Timer.schedule () 'yi lambda ifadesiyle nasıl kullanıyorsunuz (java 8'den beri)? TimerTask (ilk parametre) işlevsel bir arayüz bile değildir. TimerTask sadece soyut bir sınıf.
User8500049

25

Bunu kullan

long startTime = System.currentTimeMillis();
long elapsedTime = 0L.

while (elapsedTime < 2*60*1000) {
    //perform db poll/check
    elapsedTime = (new Date()).getTime() - startTime;
}

//Throw your exception

1
hmm ... bu teknik olarak işe
yarar

1
Tek doğru cevap bu. Tek bir iş parçacığı üzerinde çalışacak ve bitiş zamanını sapma olmadan hesaplayacaktır. Bir TimerTask kullanmak, bu durumda yapılacak tam olarak yanlış bir şeydir. StackOverflow'daki kaç örneğin aynı türden yanlış bir şeyi önerdiğine şaşırdım.
AgilePro

1
@thecoshman - zamanlayıcı uygulamaları, devam ederken DB işlemini KESİNMEZ, bunu da yapmaz. Her durumda, yalnızca DB işlemini başlattığınız zamanı kontrol edebilirsiniz. Bir şeyleri zamanlamak için bir "zamanlayıcıya" ihtiyacınız olduğuna dair yaygın bir yanılgı var, ama yok. Sadece bir şeyler yapmanız gerekir ve mevcut zamanı kullanarak bunu çok uzun süre yapmadığınızdan emin olun.
AgilePro

Diyelim ki bağlantıyı geri almalısınız ya da TAM 2 dakika sonra atmalısınız, bu işe yaramayacaktır. Bağlanmayı denedikten iki dakika SONRA hala bağlanamadıysanız, olacaktır. Bağlantı kontrolünün iki hafta sürdüğü bir durumda, bu, bir istisna oluşturmak için bu kadar uzun sürecektir.
thecoshman

14
Bu aslında çok kötü bir kodlama stili, çünkü while döngüsü sürekli çalışıyor ve bazı şeyleri kontrol ediyor ... işlemci için kötü ve pil ömrü için kötü.
Infinite

11

Tamam, sanırım problemini şimdi anlıyorum. Bir şeyler yapmayı denemek için Future'ı kullanabilir ve hiçbir şey olmadıysa biraz sonra zaman aşımına uğrayabilirsiniz.

Örneğin:

FutureTask<Void> task = new FutureTask<Void>(new Callable<Void>() {
  @Override
  public Void call() throws Exception {
    // Do DB stuff
    return null;
  }
});

Executor executor = Executors.newSingleThreadScheduledExecutor();
executor.execute(task);

try {
  task.get(5, TimeUnit.SECONDS);
}
catch(Exception ex) {
  // Handle your exception
}

İstisna oluşuyor ancak program sonlandırılmıyor, lütfen bu konuda bana yardım edin.
Ankita

2
Executor yerine ExecutorService sınıfını kullanabilirsiniz. Yürütücüyü durdurmak için shutdown () yöntemine sahiptir.
Ayinler

1
Yürütücüler, Callable / Runnable'ınızda özellikle işlemediğiniz istisnaları yutacaktır. Runnable / Callable'ınız istisnanın kendisini yakalayıp işleme koymazsa ve size veya ona sahipseniz size sağlanırsa, ScheduledExecutorService'i alt sınıflara ayırmanız ve afterExecute'u geçersiz kılmanız gerekir (super.afterExecute () öğesini çağırdığınızdan emin olun). AfterExecute için ikinci argüman Runnable / Callable'dan fırlatılabilir olacak
adam

3
    new java.util.Timer().schedule(new TimerTask(){
        @Override
        public void run() {
            System.out.println("Executed...");
           //your code here 
           //1000*5=5000 mlsec. i.e. 5 seconds. u can change accordngly 
        }
    },1000*5,1000*5); 

sadece kodun üstündeki zararlıyı kopyalayın, iyi çalışacaktır. İlk kez bu kodu çalıştırmak için iki kez 'zaman' verdim ve ikincisi aralık zamanı için.
Mahadev Mane

Timer dokümantasyonu bunun yerine Executor çerçevesinin kullanılmasını önerir. docs.oracle.com/javase/10/docs/api/java/util/Timer.html
Karan Khanna

1

[Android] Java kullanarak android üzerinde zamanlayıcı uygulamak isteyen biri varsa .

işlemleri gerçekleştirmek için bu gibi UI iş parçacığını kullanmanız gerekir .

Timer timer = new Timer();
timer.schedule(new TimerTask() {
           @Override
            public void run() {
                ActivityName.this.runOnUiThread(new Runnable(){
                    @Override
                      public void run() {
                       // do something
                      }        
                });
            }
        }, 2000));
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.