应用程序从主站退出时,不能停止运行。

问题描述 投票:0回答:1

我正在写一个java代码,它可以根据给定的时区在每个午夜打印一些行。例如,如果我在IST时区运行我的应用程序,我想根据CET时区的午夜打印数据,那么我给出的时间转换为CET。为此,我使用了ScheduledExecutorService方法scheduleAtFixedRate(),根据时区计算延迟。

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class MainClass {

    private ScheduledExecutorService executor = null;
    private static final long TOLERANCE_DELAY_TO_MIDNIGHT = 120000L;
    private static final int SCHEDULE_HOUR = 0;
    private static final int SCHEDULE_MINUTE = 0;
    final int ONE_DAY_MILLIS = 24 * 60 * 60 * 1000;

    public MainClass() {
        executor = Executors.newScheduledThreadPool(1);
        final Schedule schedule = new Schedule();
        this.executor.scheduleAtFixedRate(schedule, schedule.getScheduleDelay(), ONE_DAY_MILLIS, TimeUnit.MILLISECONDS);
    }

    private void printTime(final long delay) {
        final long millis = delay % 1000;
        final long second = (delay / 1000) % 60;
        final long minute = (delay / (1000 * 60)) % 60;
        final long hour = (delay / (1000 * 60 * 60)) % 24;

        final String time = String.format("%02d:%02d:%02d.%d", hour, minute, second, millis);
        System.out.println(time);
    }

    private long convertDateTimeZone(final long lngDate, final String fromTimeZone, final String toTimeZone) {
        final TimeZone toTZ = TimeZone.getTimeZone(toTimeZone);
        final Calendar toCal = Calendar.getInstance(toTZ);

        final TimeZone fromTZ = TimeZone.getTimeZone(fromTimeZone);
        final Calendar fromCal = Calendar.getInstance(fromTZ);
        fromCal.setTimeInMillis(lngDate);
        toCal.setTimeInMillis(fromCal.getTimeInMillis() + toTZ.getOffset(fromCal.getTimeInMillis())
        - TimeZone.getDefault().getOffset(fromCal.getTimeInMillis()));
        return toCal.getTimeInMillis();
    }

    private final class Schedule implements Runnable {

        private Schedule() {
            System.out.println("Scheduler started");
        }

        public void waitForMidnight() {
            long shift = getShiftToMidnight();
            System.out.println("shift to midnight = " + shift + "ms");
            while (shift > 0) {
                try {
                    Thread.sleep(shift);
                } catch (final InterruptedException e) {
                    // ignore
                }
                shift = getShiftToMidnight();
            }
        }

        //return the shift to midnight with tolerance value 2 minutes
        private long getShiftToMidnight() {
            final Calendar tomorrow = new GregorianCalendar();
            tomorrow.add(Calendar.DATE, 1);
            final Calendar tomorrow0000 = new GregorianCalendar(tomorrow.get(Calendar.YEAR),
                    tomorrow.get(Calendar.MONTH), tomorrow.get(Calendar.DATE), SCHEDULE_HOUR, SCHEDULE_MINUTE);
            final long nowTime = convertDateTimeZone(System.currentTimeMillis(), "IST", "CET");
            final long delay = tomorrow0000.getTimeInMillis() - nowTime;
            if (delay > TOLERANCE_DELAY_TO_MIDNIGHT) {
                return 0L;
            }
            return delay;
        }

        private final long getScheduleDelay() {
            System.out.println("running");
            final Calendar today = new GregorianCalendar();
            final Calendar todayMidnight = new GregorianCalendar(today.get(Calendar.YEAR), today.get(Calendar.MONTH),
                    today.get(Calendar.DATE), 24, 0, 0);
            final long currentTime = convertDateTimeZone(System.currentTimeMillis(), "IST", "CET");
            long delay = todayMidnight.getTimeInMillis() - currentTime;
            printTime(delay);
            delay = (delay < 0) ? 0 : delay;
            return delay;
        }

        @Override
        public void run() {
            System.out.println("hit");
            waitForMidnight();
            System.out.println("midnight);
        }

    }

    public static void main(final String[] args) {
        final MainClass scheculer = new MainClass();
        System.out.println("exit from main");
    }

}

问题是applicaiton在等待调用run方法之前退出main()。延迟是正确计算的,我没有得到它为什么会发生这样的情况。

java timezone runnable scheduledexecutorservice
1个回答
0
投票

你失去了executor.scheduleAtFixedRate的结果,它返回一个Future。你应该从你的main中调用future.get来停止退出,但是注意这个get()调用不会返回来允许正常退出,直到你整理出什么时候在其他地方取消你的计划任务。

© www.soinside.com 2019 - 2024. All rights reserved.