zoukankan      html  css  js  c++  java
  • 线程池和线程的应用

    在一些对写有严格要求的业务中,每一次update都是一次特别谨慎的操作,比如在一次时间较长的数据计算中,发起一项计算后,就不需要重复的发起这项计算,一是节省资源,而是防止数据重复出现导致数据错误;

    这时我们就会想到一个名词,线程,由于刚接触不久,这里就做一下简单的讲解,如有错误,欢迎指正。

    在实战项目中线程池的应用分三个步骤:

      1、创建单线程池类:

    首先创建基线程:

    public abstract class BaseComputeThread implements Runnable{/**
         * 任务名称
         */
        protected String taskName="";
        public String getTaskName() {
            return taskName;
        }
        /**
         * 任务描述
         */
        protected String taskDescription="";
        
        
        @Override
        public void run() {
            //判断依赖任务是否完成
            checkDependTasks();
            //任务执行
            try {//开始任务
                doJob();
            } catch (Exception e) {
                System.out.println("异常了");
            }
        }
        
        /**
         * 任务
         * 此方法为虚方法,实际调用子类的实现
         */
        protected abstract void doJob();
    }

    所有的线程继承基类:

    @Component
    public class TestThread extends BaseComputeThread {
        
        @Autowired
        private TestService testService;
    
        /**
         * 构造函数
         */
        public TestThread() {
            super.taskName = "TestThread";
            super.taskDescription = "我要控制的方法名称";
        }
    
        /**
         * 线程执行入口方法
         * 
         * @Exception 捕获异常
         */
        @Override
        public void run() {
            super.run();
        }
    
        @Override
        protected void doJob() {
            testService.test();
        }
    
    }

    2、创建线程, 使用单线程池,防止同一类型的计算任务同时执行多次,并引入测试线程:

    private ExecutorService testThreadpool = Executors.newSingleThreadExecutor();
    @Autowired
    private TestThread testThread;

    3、执行线程:

    testThreadpool.execute(tsetThread);

    拓展:

    有的业务需求中不仅仅要求任务单线程执行,还需要某个方法在执行中,不让该方法再次执行,或者不让改方法一段时间内再次执行:

    1、这时我们需要一个控制再次执行的类

    public class ComputeTaskController {
        private final String SUCCESS ="提交后台执行任务成功!";
        private final String RUNNING ="正在执行任务中,请稍后再试!";
        
        /**
         * 用来存储计算任务的状态的HashMap
         * key为任务名称,value为状态+“;”+时间戳的字符串
         */
        private static HashMap<String, String> taskStateMap = new HashMap<String, String>();
        
        /**
         * 判断任务是否需要执行
         * 如果短时间内执行过可以不再执行
         * @param taskName 任务名称
         * @return 
         * @throws Exception
         */
        public static boolean checkTaskState(String taskName){
            boolean ret = false;
            String taskState = taskStateMap.get(taskName);
            if(taskState==null){
                //还没有执行过
                ret = true;
            }else{
                String[] tempsStrings = taskState.split(";");
                if(tempsStrings[0].equals("0")){
                    //正在执行
                    ret = false;
                }else if(tempsStrings[0].equals("1")){
                    //任务完成
                    long lasttime = Long.parseLong(tempsStrings[1]);
                    long curtime = new Date().getTime();
                    if(curtime-lasttime>1000 * 60 * 60){
                        //一小时内执行过就不再执行
                        //return false;
                    }
                    return true;
                }else if(tempsStrings[0].equals("2")){
                    //任务异常终止
                    ret = true;
                }
            }
            return ret;
        }
        
        /**
         * 设置任务运行状态
         * @param taskName 任务名称
         * @param state 任务状态   0任务开始;1任务完成;2任务异常终止
         * @return 
         * @throws Exception
         */
        public static synchronized void setTaskState(String taskName, String state) {
            String curTimeString = String.valueOf(new Date().getTime());
            taskStateMap.put(taskName, state+";"+curTimeString);
        }
    }

    2、在需要执行任务时,修改上面第三步调用任务的方法:

    public String runTestTask(HttpServletRequest request) {
            if (!ComputeTaskController.checkTaskState("TestThread")) {
                return "任务正在执行";
            } else {
                testThreadpool.execute(testThread);
            }
            return "任务提交执行成功";
    ; }
  • 相关阅读:
    pyinstaller相关用法
    yield 与 yield from
    async /await相关知识理解
    调试程序方法pdb
    任务22-4
    任务22-2
    跳台阶
    计算三维空间某点距离原点的欧式距离
    质数判断
    罗马数字转换
  • 原文地址:https://www.cnblogs.com/bestxyl/p/8399830.html
Copyright © 2011-2022 走看看