zoukankan      html  css  js  c++  java
  • 使用多线程(newSingleThreadScheduledExecutor)创建一个定时任务

    业务场景:

    1、项目中很多场景下使用到了定时任务,一般采用job的方式

    2、一些轻量级的定时操作,如定时查数据库,将数据加载到内存中,不用频繁查数据库,可以采用多线程(newSingleThreadScheduledExecutor)的方式实现显得更轻量高效

    废话不多说,直接上代码

    (1)、创建一个接口

    package com.search.vst.search.service;
    /**
     * @desc 商圈
     * @author zhanhao
     */
    import com.search.vst.search.beans.vo.PoiBusinessAreaVo;
    
    public interface PoiBusinessAreaService {
        
        PoiBusinessAreaVo getPoiBusinessArea(String cityId, String keyWords);
    
        void updatePoiBusinessAreaConfig();
        
    }

    (2)、创建一个实现类

      

    package com.search.vst.search.service.impl;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Objects;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReentrantLock;
    import javax.annotation.PostConstruct;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import com.google.common.util.concurrent.ThreadFactoryBuilder;
    import com.search.vst.search.ENV;
    import com.search.vst.search.beans.vo.PoiBusinessAreaVo;
    import com.search.vst.search.service.PoiBusinessAreaService;
    import com.search.vst.search.service.WordTaggingDataService;
    
    @Service("poiBusinessAreaService")
    public class PoiBusinessAreaServiceImpl implements PoiBusinessAreaService {
        
        private static Log log=LogFactory.getLog(PoiBusinessAreaServiceImpl.class);
        
        @Autowired
        private  WordTaggingDataService wordTaggingDataService;
        
        private ReentrantLock trieBuildLock=new ReentrantLock();
        
        private volatile List<PoiBusinessAreaVo> poiBusinessAreaList= new ArrayList<PoiBusinessAreaVo>();
        
        private static ScheduledExecutorService ex=Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder().setNameFormat("PoiBusinessAreaService_trie_worker_%d").build());
        
        
        @PostConstruct
        protected void init() {
            ex.scheduleWithFixedDelay(new Runnable() {
                @Override
                public void run() {
                    try {
                        updatePoiBusinessAreaConfig();
                    } catch (Exception e) {
                        log.warn("updatePoiBusinessAreaConfig init error " + e.getMessage());
                    }
                }
            }, 0, 2, TimeUnit.MINUTES);
            updatePoiBusinessAreaConfigForFirstTime();
        }
        
        /**
         * 因为项目在重启的过程中,如果依赖的search_calculate也在重启,那么调用dubbo会失败,导致tire数构建失败,这里启动一个线程做多次尝试
         */
        private void updatePoiBusinessAreaConfigForFirstTime() {
            Thread loopInitThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    // 延迟一分钟执行
                    try {
                        TimeUnit.MINUTES.sleep(1);
                    } catch (InterruptedException e1) {
                    }
                    log.info(Thread.currentThread().getName() + " start!");
                    int maxTryTimes = 10;
                    int tryInterval = 20;
                    while (maxTryTimes > 0 && CollectionUtils.isEmpty(poiBusinessAreaList)) {
                        try {
                            maxTryTimes--;
                            updatePoiBusinessAreaConfig();
                        } catch (Exception e) {
                            if (ENV.isArk()) {
                                log.warn("try to update config error,times:" + maxTryTimes + "@error " + e);
                            } else {
                                log.error("try to update config error,times:" + maxTryTimes, e);
                            }
                        } finally {
                            try {
                                TimeUnit.SECONDS.sleep(tryInterval);
                            } catch (InterruptedException e) {
                                log.error("interupted ,times:" + maxTryTimes, e);
                            }
                        }
                    }
                    log.info(Thread.currentThread().getName() + " finish!");
                }
            });
            loopInitThread.setName("poi_buildTrie_loopInitThread");
            loopInitThread.start();
        }
        
        private void buildTrie() {
            List<PoiBusinessAreaVo> poiBusinessAreas = wordTaggingDataService.getPoiBusinessArea();
            this.poiBusinessAreaList = poiBusinessAreas;
        }
        
        @Override
        public void updatePoiBusinessAreaConfig() {
            boolean lockRequired = false;
            try {
                lockRequired = trieBuildLock.tryLock(10, TimeUnit.SECONDS);
                if (lockRequired) {
                    buildTrie();
                } else {
                    log.warn("lockRequired unsuccessful");
                }
            } catch (InterruptedException e) {
                log.error("lockRequired fail", e);
            } finally {
                if (lockRequired) {
                    trieBuildLock.unlock();
                }
            }
    
        }
    
        @Override
        public PoiBusinessAreaVo getPoiBusinessArea(String cityDistrictId, String keyWords) {
            if (CollectionUtils.isNotEmpty(this.poiBusinessAreaList)) {
                for (PoiBusinessAreaVo poiBusinessAreaVo : this.poiBusinessAreaList) {
                    if (Objects.equals(cityDistrictId, poiBusinessAreaVo.getCityId())
                        && Objects.equals(keyWords, poiBusinessAreaVo.getPoiBusinessArea())) {
                        return poiBusinessAreaVo;
                    }
                }
            }
            return null;
        }
    
    }

    总结:该业务场景下,一方面减少job的配置与维护,另方面减少频繁查数据库,减少数据库压力,此种方式显得更轻量

  • 相关阅读:
    npm install 错误 | gyp ERR! configure error
    AD中鼠标经过PCB走线或元器不能高亮显示连线的解决办法
    浏览器提示TLS版本过低, 要求升到TLS1.2或TLS1.3的一些问题收录
    Java.报错:The type java.lang.CharSequence cannot be resolved. It is indirectly referenced from required .class files
    Centos.安装Goaccess1.2
    Mongoose多数据库连接及实用样例
    mongodb通过profile来监控数据
    mongodb副本集 statestr状态说明/解释
    mongodb.副本集配置方法(使用keyfile认证部署)
    vsftp安装与配置for Linux
  • 原文地址:https://www.cnblogs.com/zhanh247/p/11677869.html
Copyright © 2011-2022 走看看