您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

无论使用哪种操作系统,用Java执行计划任务的最佳解决方案是什么?

无论使用哪种操作系统,用Java执行计划任务的最佳解决方案是什么?

这是我最终实现的:

public class AlarmManager {
    public static final String ALARM_CLI_FORMAT = "startalarm:";
    public static SupportedOS currentOS = SupportedOS.UNSUPPORTED_OS;

    public enum SupportedOS {
        UNSUPPORTED_OS,
        MAC_OS,
        WINDOWS,
    }

    public AlarmManager() {
        final String osName = System.getProperty("os.name");
        if (osName == null) {
            L.e("Unable to retrieve OS!");
        } else if ("Mac OS X".equals(osName)) {
            currentOS = SupportedOS.MAC_OS;
        } else if (osName.contains("Windows")) {
            currentOS = SupportedOS.WINDOWS;
        } else {
            L.e("Unsupported OS: "+osName);
        }
    }

    /**
     * Windows only: name of the scheduled task
     */
    private String getAlarmName(final long alarmId) {
        return new StringBuilder("My_Alarm_").append(alarmId).toString();
    }

    /**
     * Gets the command line to trigger an alarm
     * @param alarmId
     * @return
     */
    private String getAlarmCommandLine(final long alarmId) {
        return new StringBuilder("javaws -open ").append(ALARM_CLI_FORMAT).append(alarmId).append(" ").append(G.JNLP_URL).toString();
    }

    /**
     * Adds an alarm to the system list of scheduled tasks
     * @param when
     */
    public void createAlarm(final Calendar when) {
        // Create alarm
        // ... stuff here
        final long alarmId = 42;

        // Schedule alarm
        String[] commandLine;
        Process child;
        final String alarmCL = getAlarmCommandLine(alarmId);
        try {
            switch (currentOS) {
            case MAC_OS:
                final String cron = new SimpleDateFormat("mm HH d M '*' ").format(when.getTime()) + alarmCL;

                commandLine = new String[] {
                        "/bin/sh", "-c",
                        "crontab -l | (cat; echo \"" + cron + "\") | crontab"
                };
                child = Runtime.getRuntime().exec(commandLine);
                break;

            case WINDOWS:
                commandLine = new String[] {
                        "schtasks",
                        "/Create",
                        "/ST "+when.get(Calendar.HOUR_OF_DAY) + ":" + when.get(Calendar.MINUTE),
                        "/SC ONCE",
                        "/SD "+new SimpleDateFormat("dd/MM/yyyy").format(when.getTime()), // careful with locale here! dd/MM/yyyy or MM/dd/yyyy? I'm French! :)
                        "/TR \""+alarmCL+"\"",
                        "/TN \""+getAlarmName(alarmId)+"\"",
                        "/F",
                };
                L.d("create command: "+Util.join(commandLine, " "));
                child = Runtime.getRuntime().exec(commandLine);
                break;
            }
        } catch (final IOException e) {
            L.e("Unable to schedule alarm #"+alarmId, e);
            return;
        }

        L.i("Created alarm #"+alarmId);
    }

    /**
     * Removes an alarm from the system list of scheduled tasks
     * @param alarmId
     */
    public void removeAlarm(final long alarmId) {
        L.i("Removing alarm #"+alarmId);
        String[] commandLine;
        Process child;
        try {
            switch (currentOS) {
            case MAC_OS:
                commandLine = new String[] {
                        "/bin/sh", "-c",
                        "crontab -l | (grep -v \""+ALARM_CLI_FORMAT+"\") | crontab"
                };
                child = Runtime.getRuntime().exec(commandLine);
                break;

            case WINDOWS:
                commandLine = new String[] {
                        "schtasks",
                        "/Delete",
                        "/TN \""+getAlarmName(alarmId)+"\"",
                        "/F",
                };
                child = Runtime.getRuntime().exec(commandLine);
                break;
            }
        } catch (final IOException e) {
            L.e("Unable to remove alarm #"+alarmId, e);
        }
    }

    public void triggerAlarm(final long alarmId) {
        // Do stuff
        //...
        L.i("Hi! I'm alarm #"+alarmId);

        // Remove alarm
        removeAlarm(alarmId);
    }
}

用法很简单。使用以下命令安排新警报:

final AlarmManager m = new AlarmManager();
final Calendar cal = new GregorianCalendar();
cal.add(Calendar.MINUTE, 1);
m.createAlarm(cal);

触发这样的警报:

public static void main(final String[] args) {
    if (args.length >= 2 && args[1] != null && args[1].contains(AlarmManager.ALARM_CLI_FORMAT)) {
        try {
            final long alarmId = Long.parseLong(args[1].replace(AlarmManager.ALARM_CLI_FORMAT, ""));
            final AlarmManager m = new AlarmManager();
            m.triggerAlarm(alarmId);
        } catch (final NumberFormatException e) {
            L.e("Unable to parse alarm !", e);
        }
    }
}

在Mac OS X.6和Windows Vista上进行了测试。该类L是我的助手,System.out.printlnG保存我的全局常量(在这里,服务器上用于启动应用程序的JNLP文件)。

java 2022/1/1 18:29:40 有484人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶