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


148

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

javax.swing.timerを見つけましたが、使い方がよくわかりません。このクラスが提供するよりも簡単な方法を探しているようです。

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


5秒間待機してから何かを実行しますか、それとも5秒間他の処理を続行しますか?
ウイスキー

私は何か他のことを続けたいです
ufk

回答:


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

編集:

javadocさんのコメント

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


1
そのコードを実行すると、スレッドがリークします。終了したら、必ずタイマーをクリーンアップしてください。
skaffman、2010

1
@skaffman:javadocからのステートメントを追加しました。スケジュールを呼び出した後、本当にクリーンアップする必要がありますか?
タンジェンス

1
大丈夫かもしれませんが、そうではないかもしれません。そのコードフラグメントを複数回実行すると、スレッドを整理する手段がなく、緩いスレッドが発生します。
skaffman 2010

5
import java.util.Timer; import java.util.TimerTask;これはそうではないことをより明白にするかもしれませんjavax.swing.Timer。/注意:Swing(および実際にはAWT)を使用している場合、非イベントディスパッチスレッド(EDT)スレッドのコンポーネントを変更するために何もすべきではありません(java.util.Timerタスクは不良、javax.swing.Timerアクションは良好)。
トム・ホーティン-タックライン

2
@PaulAlexanderドキュメントによると-run cancelメソッドの最後にtimerのメソッドを呼び出すと、TimerTasksの実行スレッドがクリアされます。
Dandalf 2018

58

このようなもの:

// 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()スレッドプールをすぐに終了します。


24

使用例 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が言及しているように、短い導入については「Swingタイマーの使用方法」を参照する必要があります。


6

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

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

5

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

内部クラスの内部でアクセスさTimer tfinalているので宣言してはいけませんか?
Joshua Pinter

1
はい@JoshuaPinter、それが最終的に宣言する必要がありますが、それは明示的に、少なくともJavaの8の最終宣言する必要はありませんそれはちょうど(「事実上最後の」である必要がありますjavarevisited.blogspot.com/2015/03/...
Dandalf

4

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

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


4

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

Thread.sleep(4000);
myfunction();

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


そして、実行が4秒後に実行されることを保証するだけです。つまり、10秒後にも実行される可能性があります。
questzen

2
questzen、ここですべてのメソッドがそれを行うことがわかります。実際、OSレベルで何かをスケジュールしている場合でも、通常は、イベントまでの最小経過時間しか保証できません。
イーサン

これは実際の質問ではありませんでした
Inder R Singh 2017

私はこれに反対票を与えなければなりませんでした-目の前の質問に対する答えはまったくありません。
theMayer 2018

OPはコメントで「私は何か他のことを続けたい」と言った。このコードは明らかにそうではありません。
Abhijit Sarkar

3

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() {
                // The while is just to ignore interruption.
                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());
}

ループで呼び出される警告睡眠を与える
シャリーフ

whileちょうど中断を無視することです。
AlikElzin-kilaka

2

他のすべての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
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
このコードは質問に答えることがありますが、このコードが質問に答える理由や方法に関する追加のコンテキストを提供すると、長期的な価値が向上します。
マテウス2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.