Πώς να ορίσετε έναν χρονοδιακόπτη, ας πούμε για 2 λεπτά, για να προσπαθήσετε να συνδεθείτε σε μια βάση δεδομένων και στη συνέχεια να πετάξετε εξαίρεση εάν υπάρχει κάποιο πρόβλημα στη σύνδεση;
Έτσι, το πρώτο μέρος της απάντησης είναι πώς να κάνετε αυτό που ζητά το θέμα, καθώς έτσι το ερμήνευσα αρχικά και μερικοί άνθρωποι φάνηκε να το βρίσκουν χρήσιμο. Το ερώτημα διευκρινίστηκε έκτοτε και επέκτεινα την απάντηση για να το αντιμετωπίσω.
Ρύθμιση χρονοδιακόπτη
Πρώτα πρέπει να δημιουργήσετε έναν χρονοδιακόπτη (εδώ χρησιμοποιώ την έκδοση java.util
):
import java.util.Timer;
..
Timer timer = new Timer();
Για να εκτελέσετε την εργασία μία φορά θα πρέπει να κάνετε:
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);
Για να επαναλάβετε την εργασία μετά τη διάρκεια θα κάνατε:
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);
Καθιστώντας μια εργασία με χρονικό όριο
Για να κάνετε συγκεκριμένα αυτό που ζητάει η διευκρινισμένη ερώτηση, δηλαδή να επιχειρήσετε να εκτελέσετε μια εργασία για ένα συγκεκριμένο χρονικό διάστημα, θα μπορούσατε να κάνετε τα εξής:
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();
}
Αυτό θα εκτελεστεί κανονικά με εξαιρέσεις αν η εργασία ολοκληρωθεί μέσα σε 2 λεπτά. Αν εκτελεστεί περισσότερο από αυτό, θα πεταχτεί η εξαίρεση TimeoutException.
Ένα ζήτημα είναι ότι παρόλο που θα λάβετε μια TimeoutException μετά τα δύο λεπτά, η εργασία θα συνεχίσει στην πραγματικότητα να εκτελείται, αν και πιθανώς μια σύνδεση βάσης δεδομένων ή δικτύου θα τερματίσει τελικά το χρόνο και θα πετάξει μια εξαίρεση στο νήμα. Αλλά να γνωρίζετε ότι μπορεί να καταναλώνει πόρους μέχρι να συμβεί αυτό.
Εντάξει, νομίζω ότι τώρα καταλαβαίνω το πρόβλημά σας. Μπορείτε να χρησιμοποιήσετε ένα Future για να προσπαθήσετε να κάνετε κάτι και στη συνέχεια να κάνετε timeout μετά από λίγο αν δεν έχει συμβεί τίποτα.
Π.χ:
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
}