web-dev-qa-db-ja.com

java:特定の秒数後に関数を実行します

5秒後に実行したい特定の機能があります。 Javaでこれを行うにはどうすればよいですか?

Javax.swing.timerを見つけましたが、使用方法を本当に理解できません。このクラスが提供するものよりもずっと簡単なものを探しているようです。

簡単な使用例を追加してください。

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

編集:

javadoc 言います:

Timerオブジェクトへの最後のライブ参照がなくなり、すべての未処理のタスクの実行が完了すると、タイマーのタスク実行スレッドは正常に終了します(ガベージコレクションの対象になります)。ただし、これは発生するまでに任意の時間がかかる場合があります。

197
tangens

このようなもの:

// 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に他のさまざまなファクトリメソッドを代わりに使用できます。

また、終了したらエグゼキューターをシャットダウンすることが重要です。 shutdown()メソッドは、最後のタスクが完了するとスレッドプールを完全にシャットダウンし、これが発生するまでブロックします。 shutdownNow()は、スレッドプールをすぐに終了します。

50
skaffman

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!

このコードは1回だけ実行され、実行は3000ミリ秒(3秒)で行われます。

Camickrが言及しているように、短い紹介のために「 スイングタイマーの使用方法 」を検索する必要があります。

20
zpon

私のコードは次のとおりです。

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

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

あなたの元の質問は「スイングタイマー」に言及しています。実際に質問がSWingに関連している場合は、util.TimerではなくSwing Timerを使用する必要があります。

詳細については、「 タイマーの使用方法 」に関するSwingチュートリアルのセクションを参照してください。

4
camickr

thread.Sleep()関数を使用できます

Thread.sleep(4000);
myfunction();

関数は4秒後に実行されます。しかし、これはプログラム全体を一時停止する可能性があります...

3
dale

他のすべてのunswersでは、新しいスレッド内でコードを実行する必要があります。いくつかの単純なユースケースでは、少し待って同じスレッド/フロー内で実行を継続したい場合があります。

以下のコードはそのテクニックを示しています。これは、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();
        }
    }
}
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 にはこの機能がありますが、かなり重いです。

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