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上で自前でアニメーションをさせたりするのに使える。