ThreadHelper.java 6.91 KB
package com.yanzuoguang.util.thread;

import com.yanzuoguang.util.exception.ExceptionHelper;
import com.yanzuoguang.util.helper.DateHelper;

import java.util.Date;
import java.util.concurrent.*;
import java.util.function.Predicate;

/**
 * 线程帮助类
 *
 * @author 颜佐光
 */
public class ThreadHelper {
    private static final Object threadLock = new Object();
    private static boolean threadIsRun = false;
    private static Date threadDate = null;
    private static RunPlan timeout;
    private static RunPlan interval;
    private static final long SECOND_UNIT = 1000;
    private static final long NEXT_SECOND = 5;
    /**
     * 线程对象
     */
    private static final ExecutorService executeService = Executors.newCachedThreadPool();

    /**
     * 初始化线程对象,需要调用该函数之后才能使用
     */
    public static void init() {
        if (timeout != null || interval != null) {
            return;
        }
        threadDate = DateHelper.getDateTime("1987-11-04");
        timeout = new RunPlan();
        interval = new RunPlan();
        Runnable addExecute = new Runnable() {
            @Override
            public void run() {
                onExecuteAdd();
            }
        };
        Runnable itemExecuted = new Runnable() {
            @Override
            public void run() {
                onItemExecuted();
            }
        };
        timeout.getOnAdd().add(addExecute);
        timeout.getOnItemExecuted().add(itemExecuted);
        interval.getOnAdd().add(addExecute);
        interval.getOnItemExecuted().add(itemExecuted);
        startMonitor();
    }

    private static void onItemExecuted() {
        threadDate = new Date();
    }

    private static void onExecuteAdd() {
        startThread();
    }

    private static void startThread() {
        synchronized (threadLock) {
            if (threadIsRun) {
                return;
            }
            runThread(new Runnable() {
                @Override
                public void run() {
                    threadIsRun = true;
                    while (threadIsRun) {
                        try {
                            timeout.run(true, -1);
                        } catch (Exception ex) {
                            ExceptionHelper.handleException(ThreadHelper.class, ex);
                        }
                        try {
                            interval.run(false, -1);
                        } catch (Exception ex) {
                            ExceptionHelper.handleException(ThreadHelper.class, ex);
                        }
                        if (timeout.getCount() == 0 && interval.getCount() == 0) {
                            break;
                        }
                        sleep(10);
                    }
                    threadIsRun = false;
                }
            });
        }
    }

    /**
     * 监控线程的方法,防止线程执行死机
     */
    private static void startMonitor() {
        runThread(() -> {
            do {
                if (threadIsRun && ((System.currentTimeMillis() - threadDate.getTime()) / SECOND_UNIT) > NEXT_SECOND) {
                    try {
                        if (threadIsRun) {
                            threadIsRun = false;
                        }
                    } catch (Exception ex) {
                        ExceptionHelper.handleException(ThreadHelper.class, ex);
                    }
                    threadIsRun = false;
                    startThread();
                }
                sleep(1000 * 60);
            } while (true);
        });
    }

    /**
     * 多少毫秒后执行任务,适用于执行时间短,不需要单独开线程的程序
     *
     * @param run   需要执行的程序
     * @param vTime 间隔时间
     * @return 执行标志
     */
    public static String setTimeout(Runnable run, int vTime) {
        return timeout.set(run, vTime);
    }

    /**
     * 清除需要执行的任务
     *
     * @param flag 执行标志
     */
    public static void clearTimeout(String flag) {
        timeout.remove(flag);
    }

    /**
     * 清除需要执行的任务
     *
     * @param run 执行的方法,注意有多个同样的方法时,只会清除第一个
     */
    public static void clearTimeout(Runnable run) {
        timeout.remove(run);
    }

    /**
     * 每隔多少毫秒执行任务,适用于执行时间短,不需要单独开线程的程序
     *
     * @param run   需要执行的程序
     * @param vTime 间隔时间
     * @return 执行标志
     */
    public static String setInterval(Runnable run, int vTime) {
        return interval.set(run, vTime);
    }

    /**
     * 清除需要执行的任务
     *
     * @param flag 执行标志
     */
    public static void clearInterval(String flag) {
        interval.remove(flag);
    }

    /**
     * 清除需要执行的任务
     *
     * @param run 执行的方法,注意有多个同样的方法时,只会清除第一个
     */
    public static void clearInterval(Runnable run) {
        interval.remove(run);
    }

    /**
     * 沉睡
     *
     * @param mills 时间(毫秒)
     */
    public static void sleep(int mills) {
        try {
            Thread.sleep(mills);
        } catch (Exception ex) {
            ExceptionHelper.handleException(ThreadHelper.class, ex, mills);
        }
    }

    /**
     * 执行对象并且处理异常
     *
     * @param run 需要执行的对象
     */
    public static void executeCatch(Runnable run) {
        try {
            run.run();
        } catch (Exception ex) {
            ExceptionHelper.handleException(ThreadHelper.class, ex, null);
        }
    }

    /**
     * 需要执行的线程
     *
     * @param run
     */
    public static void runThread(final Runnable run) {
        executeService.execute(() -> executeCatch(run));
    }

    /**
     * 循环执行事务,直到停止执行
     *
     * @param run
     */
    public static void runThread(final RunInterval run) {
        runThread(() -> {
            while (!run.isBreakFlag()) {
                try {
                    run.getCode().run();
                } catch (Exception ex) {
                    ExceptionHelper.handleException(ThreadHelper.class, ex);
                }
                sleep(run.getTime());
            }
        });
    }

    /**
     * 等待条件是否满足
     *
     * @param waitMax  等待最大值
     * @param waitItem 每次等待值
     * @param cond     判断等待条件(已等待时间)
     */
    public static void waitRun(long waitMax, int waitItem, Predicate<Long> cond) {
        long waitStart = System.currentTimeMillis();
        long waitTime = 0;
        while (cond.test(waitTime)) {
            // 等待线程同步,超过该时间则不继续等待
            ThreadHelper.sleep(waitItem);
            waitTime = System.currentTimeMillis() - waitStart;
            if (waitTime > waitMax) {
                break;
            }
        }
    }
}