web-dev-qa-db-fra.com

java: lancer une fonction après un nombre spécifique de secondes

J'ai une fonction spécifique que je veux exécuter après 5 secondes. Comment puis-je faire cela en Java?

J'ai trouvé javax.swing.timer, mais je ne comprends pas vraiment comment l'utiliser. Il semble que je cherche quelque chose de beaucoup plus simple que ce que propose ce cours.

Veuillez ajouter un exemple d'utilisation simple.

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

EDIT:

javadoc dit:

Une fois que la dernière référence en direct à un objet Timer a disparu et que l'exécution de toutes les tâches en attente est terminée, le fil d'exécution de la tâche du minuteur se termine normalement (et devient sujet à un garbage collection). Cependant, cela peut prendre un temps arbitraire.

204
tangens

Quelque chose comme ça:

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

Il existe diverses autres méthodes d'usine sur Executor que vous pouvez utiliser à la place si vous voulez plus de threads dans le pool.

Et rappelez-vous, il est important d'arrêter l'exécuteur lorsque vous avez terminé. La méthode shutdown() ferme proprement le pool de threads à la fin de la dernière tâche et bloque jusqu'à ce que cela se produise. shutdownNow() mettra immédiatement fin au pool de threads.

50
skaffman

Exemple d'utilisation de 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!

Ce code ne sera exécuté qu'une seule fois et son exécution aura lieu en 3000 ms (3 secondes).

Comme camickr le mentionne, vous devriez chercher " Comment utiliser les minuteries Swing " pour une brève introduction.

21
zpon

Mon code est le suivant:

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

En réponse à @tangens, répondez: si vous ne pouvez pas attendre que le ramasse-miettes nettoie votre thread, annulez le chronomètre à la fin de votre méthode d’exécution.

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

Votre question initiale mentionne le "minuteur tournant". Si, en fait, votre question concerne SWing, vous devriez utiliser le minuteur Swing et non le minuteur util.

Lisez la section du tutoriel Swing sur " Comment utiliser les minuteries " pour plus d'informations.

4
camickr

vous pouvez utiliser la fonction Thread.Sleep ()

Thread.sleep(4000);
myfunction();

Votre fonction s'exécutera après 4 secondes. Cependant, cela pourrait mettre en pause tout le programme ...

3
dale

Tous les autres unswers nécessitent d’exécuter votre code dans un nouveau thread. Dans certains cas d'utilisation simples, vous pouvez simplement attendre un peu et continuer l'exécution dans le même thread/flux.

Le code ci-dessous illustre cette technique. Gardez à l'esprit que cela ressemble à ce que Java.util.Timer fait sous le capot, mais plus léger.

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

Retarder la mise en œuvre

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
Valchkou
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
Amol K

ScheduledThreadPoolExecutor a cette capacité, mais elle est assez lourde.

Timer a aussi cette capacité mais ouvre plusieurs threads même s’il n’est utilisé qu’une seule fois.

Voici une implémentation simple avec un test (signature proche de celle de Android Handler.postDelayed () ):

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() {
                while (true) {
                    try {
                        long leftToSleep = requested + delayMillis - System.currentTimeMillis();
                        if (leftToSleep > 0) {
                            Thread.sleep(leftToSleep);
                        }
                        break;
                    } catch (InterruptedException ignored) {
                    }
                }
                runnable.run();
            }
        }).start();
    }
}

Tester:

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