动态设置定时任务,没有固化到数据库中(在杜福忠大哥定时任务工具修改,拾人牙慧)

这是plugin代码

public class taskplugin implements IPlugin {
    //private static final Map<String, MyScheduler> SCHEDULER_MAP = new ConcurrentHashMap<>();
private static  Map<String, MyScheduler> MAP;
    public taskplugin() {}
    @Override
    public boolean start() {
        LogKit.info("Starting taskplugin...");
        if (MAP != null) {
return true;
}
        MAP=taskkit.getInstance().createschedulermap();
        System.out.println("taskplugin--start"+MAP.size());
        return true;
    }
    @Override
    public boolean stop() {
        LogKit.info("Stopping taskplugin...");
        taskkit.remove();
        return true;
    }    
}

这是工具类

public class taskkit {
private static  Map<String, MyScheduler> MAP = new ConcurrentHashMap<>();
// 使用 volatile 确保多线程下的可见性
private static volatile taskkit INSTANCE;

// 私有构造防止外部实例化
private taskkit() {
}

/**
* 获取 Cron4jKit 单例实例
* 
* @return Cron4jKit 实例
*/
public static taskkit getInstance() {
if (INSTANCE == null) {
synchronized (taskkit.class) {
if (INSTANCE == null) {
INSTANCE = new taskkit();
}
}
}
return INSTANCE;
}
/**
* jfinal启动加载taskplugin时创建MAP
*/
public static Map<String, MyScheduler> createschedulermap(){
return MAP;
}
/**
* 添加一个定时任务
* 
* @param configName 任务名称
* @param cron       表达式调试任务
* @param daemon     表示调试线程是否设置为守护线程,默认值为 true,守护线程会在 tomcat 关闭时自动关闭
* @param runnable   执行的任务
* @return
*/
public static MyScheduler put(String configName, String cron, boolean daemon, Runnable runnable) {
MyScheduler scheduler = new MyScheduler(configName, cron, daemon, runnable);
MAP.put(configName, scheduler);
start(configName);
return scheduler;
}

public static MyScheduler get(String configName) {
return MAP.get(configName);
}

public static List<Entry<String, MyScheduler>> getAllScheduler() {
System.out.println(MAP);
return new ArrayList<>(MAP.entrySet());
}

/**
* 启动指定任务
* 
* @param configName
*/
public static void start(String configName) {
final MyScheduler scheduler = get(configName);
if (scheduler != null && !scheduler.getScheduler().isStarted()) {
scheduler.getScheduler().start();
}
}

/**
* 启动全部任务
*/
public static void start() {
for (final String configName : MAP.keySet()) {
start(configName);
}
}

/**
* 任务停止
*/
public static void stop(String configName) {
final MyScheduler scheduler = get(configName);
if (scheduler != null && scheduler.getScheduler().isStarted()) {
scheduler.getScheduler().stop();
}
}

/**
* 任务全部停止
*/
public static void stop() {
for (final String configName : MAP.keySet()) {
stop(configName);
}
}

/**
* 删除任务
* 
* @param configName
*/
public static void remove(String configName) {
stop(configName);
MAP.remove(configName);
}

/**
* 删除全部任务
*/
public static void remove() {
stop();
MAP.clear();
}

/**
* 立即执行
* 
* @param configName
*/
public static void run(String configName) {
final MyScheduler scheduler = get(configName);
if (scheduler != null) {
scheduler.getRunnable().run();
}
}

/**
* 立即执行全部任务
*/
public static void run() {
for (final String configName : MAP.keySet()) {
run(configName);
}
}

/**
* 反射Runnable对象
* 
* @param className
* @return
*/
public static Runnable newRunnable(String className) {
try {
Object obj = Class.forName(className).newInstance();
if (obj instanceof Runnable) {
return (Runnable) obj;
}
throw new IllegalStateException(className + "必须声明Runnable接口");
} catch (Exception e) {
throw new IllegalStateException(e);
}
}

@Override
public String toString() {
return MAP.toString();
}

}

这是controller

public void index() {

try {
List<Entry<String,MyScheduler>> tasks=taskkit.getAllScheduler();
System.out.println(tasks);
JSONArray taskjson = new JSONArray();
for(Entry<String,MyScheduler> item :tasks) {
JSONObject json = new JSONObject();
json.set("configname", item.getValue().getConfigName());
json.set("cron", item.getValue().getCron());
json.set("taskclass",item.getValue().getRunnable().getClass().getName());
json.set("status",item.getValue().getScheduler().isStarted()?"运行中":"未运行");
taskjson.add(json);
}
setAttr("tasksjson", taskjson);
setAttr("taskclass",tasksrv.getAlltask());
render("taskmanager.html");
} catch (Exception e) {
e.printStackTrace();
renderText("获取定时任务异常");
}
	}

我觉得我在MAP那思考的不好,不应该那么启动插件,算是抛砖引玉吧,我为什么要单独做成插件呢?我这项目莫名奇妙的过些时间map丢失,前台获取不到任务列表了,但是任务还在运行,所以我就想着是不是对象管理的问题就放着ehcache插件改成这样子了


评论区

JFinal

2026-02-06 18:03

赞!

处理好任务的创建、start()、stop() 可动态创建、使用、停止任务。

面具的惊奇

2026-02-06 18:12

@JFinal 谢谢波哥,我这也是抄作业!还是你们的思路好!

杜福忠

2026-02-06 20:14

@面具的惊奇 👍 工具适合自己项目就是最好的

热门分享

扫码入社