Javaで定期的に処理を実行する方法についていくつか例をあげてみる。
まずは、シンプルにThreadクラスを使う方法である。
public class Main { static volatile boolean runFlag = true; /** * @param args */ public static void main(String[] args) { final Thread t = new Thread(new Runnable() { @Override public void run() { while(runFlag){ try { // ここに繰り返し処理を書く System.out.println("action."); Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } }); t.start(); // 5秒待つ try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } runFlag = false; try { t.join(); } catch (InterruptedException e) { e.printStackTrace(); } } }
最もシンプルな方法ではあるが、フラグを使ったりして少々ややこしい。
あと、Javaだとsleep()やjoin()でもExceptionをキャッチする必要があるので、少々わずらわしい。
次は、java.util.Timerクラスを使ってみた方法である。
public class Main { /** * @param args */ public static void main(String[] args) { final Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { // ここに繰り返し処理を書く System.out.println("action."); } },0,500); // 5秒待つ try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } timer.cancel(); } }
先ほどの例よりも、多少すっきりした感じがする。Timerのcancel()メソッドを呼び忘れると、いつまでたってもスレッドが残ってしまうので、注意が必要である。
他に、J2SE5から追加されたconcurrentパッケージにあるScheduledExecutorServiceを使う方法もある。
そのプログラムは以下のようになる。
public class Main { /** * @param args */ public static void main(String[] args) { final ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor(); ses.scheduleAtFixedRate(new Runnable() { @Override public void run() { // ここに繰り返し処理を書く System.out.println("action."); } }, 0, 500, TimeUnit.MILLISECONDS); // 5秒待つ try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } ses.shutdown(); } }
こちらも、Timerクラスを使ったときと似たような感じになる。ScheduledExecutorServiceを止めるメソッドはshutdown()である。
正直この例だとTimerクラスとの違いが良く分からないのだが、ScheduledExecutorServiceを使ったほうがより柔軟に時間単位などを指定できる。
8行目、ExecutorsのnewSingleThreadScheduledExecutor()を呼ぶときにThreadFactoryを引数にとる方のメソッドを使えば、Executorで使うスレッドの生成も柔軟にコントロールできるだろう。
このような定期的に処理を実行する処理は、例えばAndroid上で自前でアニメーションをさせたりするのに使える。