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

com.redismq.delay.DelayTimeoutTask Maven / Gradle / Ivy

There is a newer version: 1.2.1
Show newest version
package com.redismq.delay;

import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import static com.redismq.constant.StateConstant.RUNNING;
import static com.redismq.constant.StateConstant.STOP;
import static com.redismq.delay.DelayTimeoutTaskManager.EXECUTOR;

/**
 * @Author: hzh
 * @Date: 2022/4/25 12:05
 * 延时任务  一个虚拟队列一个任务实例DelayTimeoutTask
 */
public abstract class DelayTimeoutTask {
    protected static final Logger log = LoggerFactory.getLogger(DelayTimeoutTask.class);
    //时间轮
    private final HashedWheelTimer timer = new HashedWheelTimer(new DefaultThreadFactory("REDISMQ-HashedWheelTimer-WORKER"), 100, TimeUnit.MILLISECONDS, 1024, false);
    private final Map timeoutTaskMap = new ConcurrentHashMap<>();
    private volatile int state = RUNNING;

    public static class TimeoutTask {
        private final long startTime;
        private final Timeout task;

        public TimeoutTask(long startTime, Timeout task) {
            super();
            this.startTime = startTime;
            this.task = task;
        }

        public long getStartTime() {
            return startTime;
        }

        public Timeout getTask() {
            return task;
        }

    }

    private final AtomicReference lastTimeoutTask = new AtomicReference<>();

    public void start(Long startTime) {
        scheduleTask(startTime);
    }

    public void stop() {
        timer.stop();
        state = STOP;
    }

    private void scheduleTask(final Long startTime) {
        if (startTime == null || !isRunning()) {
            //结束本次循环调用
            return;
        }
        //已经存在相同时间的任务
        TimeoutTask timeoutTask = timeoutTaskMap.get(startTime);
        if (timeoutTask!=null){
            return;
        }
        long delay = startTime - System.currentTimeMillis();
      
        if (delay > 10) {
            // 加入时间轮执行
            long l = timer.pendingTimeouts();
            Timeout timeout = timer.newTimeout(t -> {
                try {
                    invokeTask();
                } finally {
                    //任务执行完清理缓存
                    timeoutTaskMap.remove(startTime);
                }
            }, delay, TimeUnit.MILLISECONDS);
            TimeoutTask newTimeTask = new TimeoutTask(startTime, timeout);
            timeoutTaskMap.put(startTime,newTimeTask);
        } else {
            //立即执行
            invokeTask();
        }
    }

    public boolean isRunning() {
        return state == RUNNING;
    }

    protected abstract Set pullTask();

    private void invokeTask() {
        Runnable runnable = () -> {
           
            if (isRunning()) {
                //执行真正任务
                Set nextTimes = pullTask();
                if (!CollectionUtils.isEmpty(nextTimes)) {
                    //重复调用
                    for (Long nextTime : nextTimes) {
                        scheduleTask(nextTime);
                    }
                }
            }
        };
        EXECUTOR.execute(runnable);
    }

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy