Shoeisha Technology Media

CodeZine(コードジン)

特集ページ一覧

Java入門 (9) - タイマーとスレッド

作って覚えるJavaプログラミングのススメ 第9回

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2008/06/24 14:00

今回は、タイマーを使ったプログラムの定期実行処理について考えてみましょう。また、より時間のかかる処理へ対応するため、独立したスレッドで処理を実行させる方法についても説明します。

目次

はじめに

 プログラムとは「いったんボタンをクリックしたら、処理の実行が終わるまでじっと待つもの」というイメージがあるかもしれません。しかし、処理の終了が明確に決められておらず、「常に動き続けるプログラム」もあります。

 例えば、画面上に時計を表示するプログラムを考えてみましょう。時計はユーザーが何らかのアクションを行わなくても、毎秒現在の時刻が表示されるようになっています。さて、このような動作を実現するには、どう実装をすればよいと思いますか?

 ループでエンドレスに処理を行うようなプログラムを書くわけにはいきません。いったん起動してしまったが最後、他の処理をまったく行えなくなってしまいます。

 このようなシチュエーションでは、定期的に処理を実行する「タイマー」や、メインプログラムから独立して処理を実行する「スレッド」などの機能を用います。今回は、先ほどの時計のような「メイン処理から独立して動く処理」の作り方について解説します。

対象読者

  • Javaに興味はある、けれどプログラミング経験がない、という人
  • Javaに興味はある、けれど何から手をつければいいかわからない、という人
  • Javaに興味はない、でも何でもいいからプログラミングをしたい、という人

タイマーによる定期的な処理の実行

 実は、時計のようなプログラムは「常に動いている」必要はありません。毎秒表示を現在時刻に更新することさえできれば良いのですから、1秒間隔(あるいはもう少し短いタイムラグ)で定期的に処理を実行できれば十分です。時刻を表示する処理は瞬時に終わりますから、定期的に呼び出すことによる負荷を心配する必要はないでしょう。

 さて、上記のような場合に用いるのがタイマーという機能です。Javaのタイマーにはいくつか種類がありますが、一般的に用いられるのはjava.util.Timerクラスです。このクラスのインスタンスを作成し、スケジュールを指定すると任意の処理を定期的に実行できるようになります。実行したい処理の内容は、TimerTaskクラス、もしくはそのサブクラスとして用意します。では、タイマーを利用したコードの基本的な書き方を整理しておきましょう。

Timerクラスのインスタンス生成とスケジュール指定
[変数] = new Timer();
[変数].schedule( [TimerTask], 遅延時間 ); /* 遅延時間―ミリ秒単位のlong値 */
TimerTaskクラスの定義
classクラス extends TimerTask {

    public void run(){

        ……定期実行する処理……

    }
}

 まずTimerTaskクラスのrunメソッドに、定期的に実行した処理の内容を記述しておきます。次にTimerクラスのインスタンスを作成します。その後scheduleメソッドを使ってあらかじめ作成したTimerTaskクラスを指定し、実行スケジュールの設定を行ってください。

 指定した遅延時間が経過すると、TimerTaskクラスのrunメソッドが実行されます。「TimerからTimerTask内のrunへ」という処理の流れが頭に入っていれば、それほど難しい仕組みではありません。

時刻表示Labelを作成する

 では、簡単なタイマー利用の例として、「現在時刻を表示するLabel」を作成してみましょう。ざっとタイマーの処理が頭に入っていれば、それほど難しいものではありません。

時計表示Labelの作成
package codezine.java;

import java.awt.*;
import java.text.*;
import java.util.*;
import java.util.Timer;

import javax.swing.*;

public class Sample extends JFrame {
    private static final long serialVersionUID = 1L;

    public static void main(String args[]) {
        Sample sample1 = new Sample();
        sample1.setBounds(100,100,300,200);
        sample1.setVisible(true);
    }

    public Sample() {
        TimeLabel label = new TimeLabel();
        this.add(label,BorderLayout.CENTER);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}

class TimeLabel extends JLabel {
    private DateFormat format;
    
    public TimeLabel(){
        this.setFont(new Font("Dialog",Font.BOLD,24));
        format = new SimpleDateFormat("HH:mm:ss");
        Timer t = new Timer();
        t.schedule(new TimerLabelTask(), 0,1000);
    }
    
    public void setTime(){
        Calendar calendar = Calendar.getInstance(Locale.JAPAN);
        this.setText(format.format(calendar.getTime()));
    }
    
    class TimerLabelTask extends TimerTask {
        
        public void run(){
            setTime();
        }
    }
}
実行すると現在の時刻をリアルタイム表示。タイマーを使って定期的に処理を実行させている。
実行すると現在の時刻をリアルタイム表示。タイマーを使って定期的に処理を実行させている。

 JLabelを継承したTimeLabelクラスを作成し、タイマー機能を組み込んで(ほぼ)1秒ごとに現在の時刻を表示するようにしてあります。サンプルコードでは定期的に実行したい処理の内容をsetTimeメソッドとしてまとめました。内部では現在時刻の取得と所定フォーマットでの表示を行っています。

 ところでソースコードのインポート文を見ると、import java.util.*;とは別に、import java.util.Timer;という宣言を行っています。これは、java.util.Timerクラスを優先的に利用するようにするための措置です。

 後述しますが、実は「Timer」という名前のクラスは他のパッケージにもあります。どの「Timer」クラスを使えば良いのかわからない、という事態を避けるためには、上述のように明示的なimportを行います。こうすることによって、ソースコード内の「Timer」はjava.util.Timerのことですよ、と示しているのです。


  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 掌田 津耶乃(ショウダ ツヤノ)

    三文ライター&三流プログラマ。主にビギナーに向けたプログラミング関連の執筆を中心に活動している。 ※現在、入門ドキュメントサイト「libro」、カード型学習サイト「CARD.tuyano.com」を公開中。またGoogle+プロフィールはこちら。

バックナンバー

連載:作って覚えるJavaプログラミングのススメ

もっと読む

All contents copyright © 2005-2019 Shoeisha Co., Ltd. All rights reserved. ver.1.5