守护线程的使用

最近有个需求,当一个线程开始时,需要实时判断这个线程是否存在,去修改一些值。

场景:.现在需要迁移一个公司的数据,异步操作。在系统中公司的数据如果在迁移,不能重复迁移。

// 发起迁移数据的进口,这里因为这个操作不常用,所以没有用线程池。
// 原因是,守护线程的限制。线程池,只是把线程放回线程池,没有销毁,所以守护线程无法判断到这个线程已经完成。
// 如果要使用线程池,可以在心跳守护线程中手动设置一个值控制
Thread thread= new Thread(new Runnable() { @Override public void run() { try { HeartbeatHelper.start(2, comId + "_" + module + "_trans"); dataTansService.dataTransfer(comId, module, instance); } catch (Exception e) { LOGGER.error("迁移公司[" + comId + "]的数据失败,原因:" + e.getMessage(), e); } } }); thread.start();
public class HeartbeatHelper {

    /**
     * 心跳缓存关键字前缀
     */
    private static final String ERP_HEARTBEAT_KEY_PREFIX = "HEARTBEAT_KEY_PREFIX_";
    private static CacheFacade cacheFacade = ApplicationContextManager.getBean(CacheFacade.class);
    
    /**
     * 启动心跳
     * @param key 关键字
     */
    public static void start(String key) {
        new HeartbeatDaemon(key).start();
    }

    /**
     * 判断心跳线程是否存在
     */
    public static boolean isLive(String key) {
        return PlatformUtils.hasText(cacheFacade.get(wrapKey(key)));
    }

    public static String wrapKey(String key) {
        return ERP_HEARTBEAT_KEY_PREFIX + key;
    }

    /**
     * 启动心跳
     * @param minute 心跳频率,单位分钟
     * @param key 关键字
     */
    public static HeartbeatDaemon start(int minute, String key) {
        HeartbeatDaemon daemon = new HeartbeatDaemon(minute,key);
        daemon.start();
        return daemon;
    }

    public static class HeartbeatDaemon extends Thread {

        /**
         * 守护的对象:即为创建该守护线程的线程对象
         */
        private final Thread guard;
        private static final String NAME_PREFIX = "guarding_";
        /**
         * 心跳频率为10分钟1次
         */
        private static final int HEART_RATE = 10;
        /**
         * 心跳频率,单位分钟
         */
        private final int rate;
        /**
         * 缓存关键字
         */
        private final String key;

        private Logger logger = LoggerFactory.getLogger(HeartbeatHelper.class);

        public HeartbeatDaemon(int minute, String key) {
            this.rate = minute * CommonPlatformConstant.SECOND_MINUTE;
            this.key = key;
            setDaemon(true);
            guard = Thread.currentThread();
            setName(NAME_PREFIX + guard.getName());
        }

        public HeartbeatDaemon(String key) {
            this(HEART_RATE, key);
        }

        @Override
        public void run() {
            while (guard.isAlive()) {
         // 守护的线程活着的时候做的事情
try {
             cacheFacade.set(wrapKey(key), DateUtils.formatDateTime(
new Date()), rate); } catch (Exception e) { logger.error("更新心跳失败:" + e.getMessage(), e); } try { // 休眠时间应该小于键的有效时间 Thread.sleep((rate -1) * CommonPlatformConstant.SECOND_OF_MILLISECOND); } catch (InterruptedException e) { logger.error("更新心跳休眠失败:" + e.getMessage(), e); } } } } }

 

posted on 2019-03-20 10:18  钉子His  阅读(776)  评论(0编辑  收藏  举报

导航