Java 定期実行 Windows終了とともにプログラム終了

会社の安全衛生の関係で、精神的健康のため、休憩をきちんととりましょうのキャンペーンを行う事になった。物理的に何か買うとお金かかるし、ほとんどの人がPC業務のため、休憩時間をお知らせするプログラムをパパッと作ってみました。

前提条件

  1. 10:00、12:00、15:00に休憩を知らせる窓がでること
  2. 一度警告を出した後にも、次の休憩を知らせること
  3. 対象はWindowsXP。もしPCをシャットダウン時は、エラーなしで終了すること

使用する言語

Javaで作ります。なぜWindowsなのにJavaかって?正直MS系の言語あんまりで、しかもXP用だと今後サポートの関係が…。本当はGroovy使いたいところですが、まだちょっと知識が足りず…。(今NetBeans使っていますが、GroovyプラグインがJarファイル作成時にGrooby-allも一緒にビルドしてくれるみたいだから、意外にできるかもしれませんが…。

作成したソース

メインメソッド BreakTimerThreadMain.java
Windowsのシャットダウン時にうまく終了するように、JVMの終了にフックさせて終了する。

package breaktimer;

public class BreakTimerThreadMain {

    public static void main(String[] args)
    {
       Runtime.getRuntime().addShutdownHook(new BreakTimerFookVMThread());
       BreakTimerThread btt = new BreakTimerThread();
       btt.start();
    }
}

シャットダウン時に実行される終了スレッド BreakTimerFookVMThread.java
プログラムを終了する。

package breaktimer;

public class BreakTimerFookVMThread extends Thread
{
    @Override
    public void run()
    {
        System.exit(0);    
    }
}

タイマー実行スレッド本体 BreakTimerThread.java
タイマーにように動くスレッド。時刻の比較は面倒だが、ごくごく単純な数値比較だけで乗りきりました。現時刻が目標のhourと全然関わりない場合は、スリープ時間を長くしています。

package breaktimer;

import java.util.Calendar;
import java.util.concurrent.TimeUnit;

public class BreakTimerThread extends Thread
{
    @Override
    public void run()
    {
        final int[] TARGET_HOUR={10 , 12 , 15};
        final int TARGET_MINUTES_UPPER = 0;
        final int TARGET_MINUTES_LOWER = 1;
        final String BTFTITLE = "休憩のお知らせ";
       
        final int CYCLE = 60 * 1000;
        final long HOUR_CYCLE = 60*60*1000;
       
        while(true)
        {
            try
            {
               //現在時刻取得
               Calendar nowtime = Calendar.getInstance();
               long wait = 0;
       
               for(int i =0 ; i < TARGET_HOUR.length ; i++)
               {
                    if(nowtime.get(Calendar.HOUR_OF_DAY) == TARGET_HOUR[i])
                    {
                        if(nowtime.get(Calendar.MINUTE) >= TARGET_MINUTES_UPPER
                            && nowtime.get(Calendar.MINUTE) <= TARGET_MINUTES_LOWER)
                        {
                            //必要な画面表示処理
                            //ただし、xボタンのデフォルトの挙動を変更する必要あり                    
                        }
                       
                        wait = CYCLE;
                    }
                    else if(nowtime.get(Calendar.HOUR_OF_DAY) == TARGET_HOUR[i] - 1)
                    {
                        wait = CYCLE;
                    }                   
                }
              
                if(wait == 0)
                {
                    wait = HOUR_CYCLE;
                }
               
                TimeUnit.MILLISECONDS.sleep(wait);
            }
            catch(Exception e)
            {
                System.exit(0);
            }
        }
    }
}

実行結果

時間になるとお知らせ画面が表示され、かつシャットダウン時にエラーは出ませんでした。

参考

かずきのブログ 様 JavaVMの終了時に処理をするには