All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.cm.heclouds.adapter.utils.ScheduledExecutorTimer Maven / Gradle / Ivy

There is a newer version: 1.0.4
Show newest version
/*
 * Copyright (C) 2018 Issey Yamakoshi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.github.cm.heclouds.adapter.utils;


import com.github.cm.heclouds.adapter.api.ConfigUtils;
import com.github.cm.heclouds.adapter.core.logging.ILogger;
import io.netty.util.Timeout;
import io.netty.util.Timer;
import io.netty.util.TimerTask;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.*;

import static com.github.cm.heclouds.adapter.core.logging.LoggerFormat.Action.RUNTIME;

/**
 * 定时任务,用于Mqtt Client
 */
public final class ScheduledExecutorTimer implements Timer {

    private final Map timeouts = new WeakHashMap<>();
    private final ScheduledExecutorService executor;

    private boolean stopped = false;

    public ScheduledExecutorTimer(ScheduledExecutorService executor) {
        this.executor = executor;
    }

    @Override
    public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {
        if (stopped) {
            throw new IllegalStateException("cannot be started once stopped");
        }
        return new ScheduledExecutorTimeout(this, task, delay, unit);
    }

    @Override
    public Set stop() {
        this.stopped = true;
        final Set unfinished;
        synchronized (timeouts) {
            unfinished = new HashSet<>(timeouts.keySet());
        }
        for (Timeout timeout : unfinished) {
            timeout.cancel();
        }
        return unfinished;
    }

    private ScheduledFuture register(TimeoutRunner timeout, long delay, TimeUnit unit) {
        synchronized (timeouts) {
            if (timeouts.containsKey(timeout)) {
                throw new RejectedExecutionException("timeout has already been bound");
            }
            ScheduledFuture future = executor.schedule(timeout, delay, unit);
            timeouts.put(timeout, null);
            return future;
        }
    }

    private void unregister(TimeoutRunner timeout) {
        synchronized (timeouts) {
            timeouts.remove(timeout);
        }
    }

    private interface TimeoutRunner extends Timeout, Callable {
    }

    private static final class ScheduledExecutorTimeout implements TimeoutRunner {

        private static final ILogger LOGGER = ConfigUtils.getLogger();

        private final ScheduledExecutorTimer timer;
        private final TimerTask task;
        private final ScheduledFuture future;

        ScheduledExecutorTimeout(ScheduledExecutorTimer timer, TimerTask task,
                                 long delay, TimeUnit unit) {

            this.timer = timer;
            this.task = task;
            this.future = timer.register(this, delay, unit);
        }

        @Override
        public Timer timer() {
            return timer;
        }

        @Override
        public TimerTask task() {
            return task;
        }

        @Override
        public boolean isExpired() {
            // expired is not a done of future
            return !isCancelled() && future.getDelay(TimeUnit.NANOSECONDS) <= 0;
        }

        @Override
        public boolean isCancelled() {
            return future.isCancelled();
        }

        @Override
        public boolean cancel() {
            if (future.cancel(false)) {
                timer.unregister(this);
                return true;
            } else {
                return false;
            }
        }

        @Override
        public Void call() {
            try {
                timer.unregister(this);
                task.run(this);
            } catch (Throwable cause) {
                LOGGER.logInnerWarn(ConfigUtils.getName(), RUNTIME, "An exception was thrown by TimerTask, e:" + cause.getLocalizedMessage());
            }
            return null;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy