Java: запустить функцию через определенное количество секунд

У меня есть определенная функция, которую я хочу выполнить через 5 секунд. Как я могу сделать это на Java?

Я нашел javax.swing.timer, но я не могу понять, как его использовать. Похоже, я ищу что-то более простое, чем этот класс.

Добавьте простой пример использования.

Ответ 1

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

EDIT:

javadoc говорит:

После того, как последняя живая ссылка на объект Timer исчезнет, ​​и все невыполнимые задачи завершены, поток выполнения задачи таймера заканчивается изящно (и становится объектом сбора мусора). Однако это может занять некоторое время.

Ответ 2

Что-то вроде этого:

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

На Executor существуют другие методы factory, которые вы можете использовать вместо этого, если вам нужно больше потоков в пуле.

И помните, что важно завершить работу исполнителя, когда вы закончите. Метод shutdown() очистит пул потоков, когда завершится последняя задача, и будет блокироваться до тех пор, пока это не произойдет. shutdownNow() немедленно завершит пул потоков.

Ответ 3

Пример использования 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!

Этот код будет выполняться только один раз, а выполнение происходит в 3000 мс (3 секунды).

Как упоминает camickr, вы должны найти "Как использовать таймеры поворота" для краткого введения.

Ответ 4

вы можете использовать функцию Thread.Sleep()

Thread.sleep(4000);
myfunction();

Ваша функция будет выполняться через 4 секунды. Однако это может приостановить всю программу...

Ответ 5

Мой код выглядит следующим образом:

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

В исходном вопросе упоминается "Таймер качания". Если на самом деле ваш вопрос связан с SWing, тогда вы должны использовать таймер Swing и NOT util.Timer.

Прочтите раздел из руководства Swing по Как использовать таймеры" для получения дополнительной информации.

Ответ 7

Как вариант ответа @tangens: если вы не можете дождаться, когда сборщик мусора очистит ваш поток, отмените таймер в конце вашего метода run.

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

Ответ 8

ScheduledThreadPoolExecutor имеет эту способность, но это довольно тяжеловес.

Timer также обладает этой способностью, но открывает несколько потоков, даже если используется только один раз.

Здесь простая реализация с тестом (подпись, близкая к 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();
    }
}

Тест:

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

Ответ 9

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

Ответ 10

Все остальные ответы требуют запуска вашего кода в новом потоке. В некоторых простых случаях вы можете просто подождать немного и продолжить выполнение в том же потоке/потоке.

Код ниже демонстрирует эту технику. Имейте в виду, что это похоже на то, что java.util.Timer делает под капотом, но более легкий.

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

Реализация DelayUtil

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