package com.mortals.xhx.common.utils;

import lombok.extern.apachecommons.CommonsLog;


@CommonsLog
public abstract class AbstractThread extends Thread {
    /**
     * 线程出错记录日志间隔时间(单位:毫秒)
     */
    protected long errorIntervalTime = 2 * 60 * 1000L;

    /**
     * 线程是否运行中
     */
    protected volatile boolean running = false;

    /**
     * 线程是否正在关闭
     */
    private volatile boolean closing = false;

    /**
     * close方法等待线程关闭时间(单位:毫秒)
     */
    protected long closeWaitTime = 30 * 1000L;

    /**
     * close方法等待关闭线程休眠时间
     */
    protected long closingSleepTime = 2 * 1000L;

    public AbstractThread() {

    }

    public final void run() {
        running = true;
        closing = false;
        long lastErrorTime = 0;
        while (running) {
            try {
                if (closing) {
                    break;
                }
                sleep(getSleepTime());
                process();
            } catch (Throwable e) {
                if (System.currentTimeMillis() - lastErrorTime > errorIntervalTime) {
                    try {
                        exceptionCaught(e);
                        lastErrorTime = System.currentTimeMillis();
                    } catch (Throwable e1) {

                    }
                }
            }
        }
        closing = false;
    }

    public final void close() {
        running = false;
        closing = true;
        long closeStartTime = System.currentTimeMillis();
        while (closing && (System.currentTimeMillis() - closeStartTime < closeWaitTime)) {
            try {
                sleep(closingSleepTime);
            } catch (InterruptedException e) {
                log.error("关闭发送线程发生错误!", e);
            }
        }
        if (closing) {
            try {
                this.interrupted();
            } catch (Exception e) {

            }
        }
        threadClosed();
    }

    /**
     * 获取休眠时间(单位：毫秒)
     *
     * @return
     */
    protected abstract int getSleepTime();

    /**
     * 业务处理方法,业务处理完后休眠时间由子类决定
     */
    protected abstract void process() throws Exception;

    /**
     * 关闭后清理处理方法,由子类实现
     */
    protected abstract void threadClosed();

    /**
     * 错误日志记录,子类可以重载打印日志
     *
     * @param e
     */
    protected void exceptionCaught(Throwable e) {
        log.error("线程运行出错!", e);
    }
}
