// Path: src/main/java/com/github/otbproject/otbproject/util/ThreadUtil.java
// public class ThreadUtil {
//     public static final Thread.UncaughtExceptionHandler UNCAUGHT_EXCEPTION_HANDLER;
// 
//     private ThreadUtil() {}
// 
//     static {
//         UNCAUGHT_EXCEPTION_HANDLER = (t, e) -> {
//             App.logger.error("Thread crashed: " + t.getName());
//             App.logger.catching(e);
//             Watcher.logException();
//         };
//         Thread.setDefaultUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER);
//     }
// 
//     public static ExecutorService newSingleThreadExecutor() {
//         return Executors.newSingleThreadExecutor(newThreadFactory());
//     }
// 
//     public static ExecutorService newSingleThreadExecutor(String nameFormat) {
//         return Executors.newSingleThreadExecutor(newThreadFactory(nameFormat));
//     }
// 
//     public static ExecutorService newCachedThreadPool() {
//         return Executors.newCachedThreadPool(newThreadFactory());
//     }
// 
//     public static ExecutorService newCachedThreadPool(String nameFormat) {
//         return Executors.newCachedThreadPool(newThreadFactory(nameFormat));
//     }
// 
//     public static ThreadFactory newThreadFactory() {
//         return new ThreadFactoryBuilder()
//                 .setUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER)
//                 .build();
//     }
// 
//     public static ThreadFactory newThreadFactory(String nameFormat) {
//         return new ThreadFactoryBuilder()
//                 .setNameFormat(nameFormat)
//                 .setUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER)
//                 .build();
//     }
// 
//     public static void interruptIfInterruptedException(Exception e) {
//         if (e instanceof InterruptedException) {
//             Thread.currentThread().interrupt();
//         }
//     }
// }


import com.github.otbproject.otbproject.util.ThreadUtil;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
package com.github.otbproject.otbproject.command.scheduler;



public class Scheduler {
    private ScheduledExecutorService scheduledExecutorService;
    private volatile boolean running;
    private final ReadWriteLock lock = new ReentrantReadWriteLock(true);
    private final String channel;

    public Scheduler(String channel) {
        this.channel = channel;
    }

    private ScheduledExecutorService getService() {
// Path: src/main/java/com/github/otbproject/otbproject/util/ThreadUtil.java
// public class ThreadUtil {
//     public static final Thread.UncaughtExceptionHandler UNCAUGHT_EXCEPTION_HANDLER;
// 
//     private ThreadUtil() {}
// 
//     static {
//         UNCAUGHT_EXCEPTION_HANDLER = (t, e) -> {
//             App.logger.error("Thread crashed: " + t.getName());
//             App.logger.catching(e);
//             Watcher.logException();
//         };
//         Thread.setDefaultUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER);
//     }
// 
//     public static ExecutorService newSingleThreadExecutor() {
//         return Executors.newSingleThreadExecutor(newThreadFactory());
//     }
// 
//     public static ExecutorService newSingleThreadExecutor(String nameFormat) {
//         return Executors.newSingleThreadExecutor(newThreadFactory(nameFormat));
//     }
// 
//     public static ExecutorService newCachedThreadPool() {
//         return Executors.newCachedThreadPool(newThreadFactory());
//     }
// 
//     public static ExecutorService newCachedThreadPool(String nameFormat) {
//         return Executors.newCachedThreadPool(newThreadFactory(nameFormat));
//     }
// 
//     public static ThreadFactory newThreadFactory() {
//         return new ThreadFactoryBuilder()
//                 .setUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER)
//                 .build();
//     }
// 
//     public static ThreadFactory newThreadFactory(String nameFormat) {
//         return new ThreadFactoryBuilder()
//                 .setNameFormat(nameFormat)
//                 .setUncaughtExceptionHandler(UNCAUGHT_EXCEPTION_HANDLER)
//                 .build();
//     }
// 
//     public static void interruptIfInterruptedException(Exception e) {
//         if (e instanceof InterruptedException) {
//             Thread.currentThread().interrupt();
//         }
//     }
// }


// Path: src/main/java/com/github/otbproject/otbproject/command/scheduler/Scheduler.java
import com.github.otbproject.otbproject.util.ThreadUtil;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

package com.github.otbproject.otbproject.command.scheduler;



public class Scheduler {
    private ScheduledExecutorService scheduledExecutorService;
    private volatile boolean running;
    private final ReadWriteLock lock = new ReentrantReadWriteLock(true);
    private final String channel;

    public Scheduler(String channel) {
        this.channel = channel;
    }

    private ScheduledExecutorService getService() {
        return Executors.newSingleThreadScheduledExecutor(ThreadUtil.newThreadFactory(channel + "-scheduler"));