通过线程池设置自定义定时任务

便捷的定时异步执行

SpaceAnalysisJobService

package diit.microservice.diitmap.service;

import diit.microservice.diitmap.async.SpaceAnalysisTask;
import diit.microservice.diitmap.entity.SpaceAnalysis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Service
@EnableScheduling
public class SpaceAnalysisJobService {

    @Autowired
    private SpaceAnalysisTask spaceAnalysisTask;
    @Autowired
    private ScheduledExecutorService executor;


    @Bean
    public ScheduledExecutorService scheduledExecutorService() {
        return Executors.newSingleThreadScheduledExecutor();
    }

    int executionCount = 0; // 任务执行次数计数器
    int maxExecutionCount = 5; // 最大执行次数

    public String scheduleTasks(Map postResult, SpaceAnalysis spaceAnalysis) {

        executor.scheduleAtFixedRate(() -> {
            if (executionCount < maxExecutionCount) {
                // 调用异步任务并获取返回值
                CompletableFuture<String> future = spaceAnalysisTask.executeTask(postResult,spaceAnalysis);
                try {
                    String result = future.get();
                    System.out.println("Result: " + result);
                    if (executionCount==2){
                        executor.shutdown();
                        spaceAnalysis.setAnalysisResult("分析结果");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                executionCount++; // 更新执行次数计数器
            } else {
                executor.shutdown(); // 达到最大执行次数后停止任务调度
            }
        }, 0, 2, TimeUnit.SECONDS);

        return "任务调度开始,每2秒执行一次";
    }
}

SpaceAnalysisTask

package diit.microservice.diitmap.async;

import diit.microservice.diitmap.entity.SpaceAnalysis;
import diit.microservice.diitmap.utils.HttpClientResult;
import diit.microservice.diitmap.utils.HttpClientUtil;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.CompletableFuture;
@Component
public class SpaceAnalysisTask {

    public CompletableFuture<String> executeTask(Map postResult, SpaceAnalysis spaceAnalysis) {
        return CompletableFuture.supplyAsync(() -> {
//            for (int i = 0; i < 5; i++) {
                try {
                    // 模拟每2秒调用一次接口
                    Thread.sleep(2000);
                    // 发送POST请求
                    String urltest = "https://www.baidu.com/";
//                    String response = restTemplate.postForObject(url, null, String.class);
                    HttpClientResult result = HttpClientUtil.doPost(urltest, null);
                    return result.getContent();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
//            }
            return "All requests completed.";
        });
    }
}

通过定时产生新线程去完成任务

逻辑部分

RecordInit 初始化

package hardwareMonitor.scheduled;

import hardwareMonitor.utils.DateTimeUtil;
import lombok.SneakyThrows;
import org.springframework.boot.CommandLineRunner;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;


@EnableAsync
@Service
//通过继承接口CommandLineRunner重写里面的run方法来让系统启动后自动运行里面的run方法
public class RecordInit implements CommandLineRunner {
    @Resource
    private RecordCpu recordCpu;
    @Resource
    private RecordDisk recordDisk;
    @Resource
    private RecordJvm recordJvm;
    @Resource
    private RecordMemory recordMemory;

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    @Override
    public void run(String... args) throws Exception {

        //Timer定时任务对象
        Timer timer = new Timer();
        try {

            TimerTask timerTask = null;

            timerTask = new TimerTask() {
                //将要执行的定时任务内容
                @SneakyThrows
                @Override
                public void run() {
                    Future<String> cpuFuture = recordCpu.startRecordCpu();
                    String cpuThreadName = cpuFuture.get();
                    System.out.println("cpuThreadName: " + cpuThreadName);

                    Future<String> diskFuture = recordDisk.startRecordDisk();
                    String diskThreadName = diskFuture.get();
                    System.out.println("diskThreadName: " + diskThreadName);

                    Future<String> jvmFuture = recordJvm.startRecordJvm();
                    String jvmThreadName = jvmFuture.get();
                    System.out.println("jvmThreadName: " + jvmThreadName);

                    Future<String> memoryFuture = recordMemory.startRecordMemory();
                    String MemoryThreadName = memoryFuture.get();
                    System.out.println("MemoryThreadName: " + MemoryThreadName);
                }
            };

            Date firstTime = getNextHour();				// 设置定时器第1次执行的开始时间
            long period = TimeUnit.HOURS.toMillis(1);	// 设置每隔1小时执行1次
            timer.scheduleAtFixedRate(timerTask, firstTime, period);
        } catch (Exception e) {
            timer.cancel();
            e.printStackTrace();
        }
    }

    /** 获取当前时间的下一个小时的整点时间 */
    public  Date getNextHour() {
        Calendar calendar = Calendar.getInstance();
        System.out.println("当前时间 = " + dateFormat.format(calendar.getTime()));

        calendar.set(Calendar.MINUTE, 0);       // 清空分
        calendar.set(Calendar.SECOND, 0);       // 清空秒
        calendar.set(Calendar.MILLISECOND, 0);  // 清空毫秒
        calendar.add(Calendar.HOUR, 1); 		// 添加1小时
        Date nextHour = calendar.getTime();
        System.out.println("开始时间 = " + dateFormat.format(nextHour));
        return nextHour;
    }

}

通过线程池生成新的线程执行具体任务

package hardwareMonitor.scheduled;

import com.alibaba.fastjson.JSONObject;
import hardwareMonitor.entity.OSHICpu;
import hardwareMonitor.mapper.OSHICpuMapper;
import hardwareMonitor.utils.ToolOSInfo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.Future;

@EnableScheduling
@EnableAsync
@Component
public class RecordCpu {
    @Resource
    private OSHICpuMapper oshiCpuMapper;

    @Value("${server.addressUrl}")
    private String localIp;

    //给配置命名 通过@Async注解启动新线程
    @Async("threadPoolTaskExecutor")
    public Future<String> startRecordCpu() throws InterruptedException {

        try {
            JSONObject jsonObject = ToolOSInfo.cpuInfo();
            OSHICpu oshiCpu = new OSHICpu();
            //cpu核数
            oshiCpu.setCpuProcessorCount(jsonObject.getInteger("cpuProcessorCount"));
            //cpu系统使用率
            oshiCpu.setCpuSysUse(jsonObject.getString("cpuSysUse"));
            //cpu用户使用率
            oshiCpu.setCpuUserUse(jsonObject.getString("cpuUserUse"));
            //cpu当前等待率
            oshiCpu.setCpuWaitRate(jsonObject.getString("cpuWaitRate"));
            //cpu当前使用率
            oshiCpu.setCpuNowRate(jsonObject.getString("cpuNowRate"));
            //记录时间
            Timestamp recordingTime = new Timestamp(System.currentTimeMillis());
            oshiCpu.setRecordingTime(recordingTime);
            oshiCpu.setId(UUID.randomUUID().toString());
            oshiCpu.setLocalIp(localIp);
            oshiCpuMapper.insert(oshiCpu);
//            oshiCpuMapper.deleteOut7Day();

        } catch (Exception e) {
            e.printStackTrace();
        }
		//通过Future异步返回结果,此处返回的为线程名称
        return new AsyncResult<>(Thread.currentThread().getName());
    }
}

配置线程池

package hardwareMonitor.config;

import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync // 允许使用异步方法
public class ThreadPoolConfig {

    @Bean("threadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        threadPoolTaskExecutor.setCorePoolSize(5);
        // 设置最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(10);
        // 设置工作队列大小
        threadPoolTaskExecutor.setQueueCapacity(2000);
        // 设置线程名称前缀
        threadPoolTaskExecutor.setThreadNamePrefix("autoRun_");
        // 设置拒绝策略.当工作队列已满,线程数为最大线程数的时候,接收新任务抛出RejectedExecutionException异常
//        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //CallerRunsPolicy在任务被拒绝添加后,会用调用execute函数的上层线程去执行被拒绝的任务。
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化线程池
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    @Bean("scheduledThreadPoolTaskExecutor")
    public Executor scheduledThreadPoolTaskExecutor() {
        ScheduledThreadPoolExecutor threadPoolTaskExecutor = new ScheduledThreadPoolExecutor(5);
        // 设置核心线程数
        threadPoolTaskExecutor.setCorePoolSize(5);
        // 设置最大线程数
        threadPoolTaskExecutor.setMaximumPoolSize(10);
        // 设置工作队列大小
        // 设置线程名称前缀
        // 设置拒绝策略.当工作队列已满,线程数为最大线程数的时候,接收新任务抛出RejectedExecutionException异常
        //CallerRunsPolicy在任务被拒绝添加后,会用调用execute函数的上层线程去执行被拒绝的任务。
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化线程池
        return threadPoolTaskExecutor;
    }
}

通过新线程内定时去完成任务

启动自动运行

Controller

/**
 * 启动自动运行
 * @param id
 * @return
 */
@GetMapping("startAutoRun")
public APIResponse startAutoRun(String id){
    try {
        managementService.startAutoRun(id);
        return new APIResponse(ResponeCode.SUCCESS);
    }catch (Exception e){
        e.printStackTrace();
        return new APIResponse(ResponeCode.FAIL,e.getMessage());
    }
}

Service

@Autowired
    ApplicationContext applicationContext;
    public static Map<String, Timer> timerMap = new HashMap<String, Timer>();
@Service
@EnableAsync
public class InterfaceManagementServiceImpl extends ServiceImpl<InterfaceManagementMapper, InterfaceManagement> implements InterfaceManagementService {
    @Override
    public void startAutoRun(String id) throws InterruptedException, ExecutionException {

        InterfaceManagement management = managementMapper.selectById(id);
        if ("1".equals(management.getAuto()) && "0".equals(management.getAutoRun()) && management.getIntervalTime() != 0) {
//            AsyncInterfaceManagement asyncInterfaceManagement = new AsyncInterfaceManagement();
            AsyncInterfaceManagement asyncInterfaceManagement = applicationContext.getBean(AsyncInterfaceManagement.class);
            Future<String> future = asyncInterfaceManagement.async(management.getId(), management.getPath(), management.getIntervalTime(),timerMap);
            String threadName = future.get();
            management.setAutoRun("1");
            management.setThreadName(threadName);
            managementMapper.updateById(management);
        }
    }
}
	

Async

package diit.resourcemanage.utils;

import lombok.SneakyThrows;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Future;
@EnableAsync
@Component
public  class AsyncInterfaceManagement {

    //给配置命名 通过@Async注解启动新线程
    @Async("threadPoolTaskExecutor")
    public Future<String> async(String id, String path, Long intervalTime, Map<String, Timer> timerMap) throws InterruptedException {
        //Timer定时任务对象
        Timer timer = new Timer(id);
        TimerTask timerTask = null;
        try {
            timerTask = new TimerTask() {
                //将要执行的定时任务内容
                @SneakyThrows
                @Override
                public void run() {
                    HttpClientResult httpClientResult = HttpClientUtil.doGet(path);
                    System.out.println(httpClientResult.getContent().substring(0, 100));
                }
            };
        } catch (Exception e) {
            timer.cancel();
            e.printStackTrace();
        }
        //安排指定的任务在指定的时间开始进行重复的固定延迟执行。这里是每3秒执行一次
        //第 二个参数为时间格式毫秒(延迟多少秒后执行一次timerTask)
        //第三个参数为时间格式毫秒(隔多长时间执行timerTask一次)
        timer.schedule(timerTask, 0, intervalTime * 1000);
        timerMap.put(id, timer);
        //通过Future 获取异步线程的返回值
        return new AsyncResult<>(Thread.currentThread().getName());
    }
}

ThreadPoolConfig

package diit.resourcemanage.config;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync // 允许使用异步方法
public class ThreadPoolConfig {

    @Bean("threadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        threadPoolTaskExecutor.setCorePoolSize(5);
        // 设置最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(10);
        // 设置工作队列大小
        threadPoolTaskExecutor.setQueueCapacity(2000);
        // 设置线程名称前缀
        threadPoolTaskExecutor.setThreadNamePrefix("autoRun_");
        // 设置拒绝策略.当工作队列已满,线程数为最大线程数的时候,接收新任务抛出RejectedExecutionException异常
//        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
        //CallerRunsPolicy在任务被拒绝添加后,会用调用execute函数的上层线程去执行被拒绝的任务。
        threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化线程池
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}

关闭自动运行

Controller

	@GetMapping("stopAutoRun")
    public APIResponse stopAutoRun(String id){
        try {
            managementService.stopAutoRun(id);
            return new APIResponse(ResponeCode.SUCCESS);
        }catch (ConcurrentModificationException e){
            return new APIResponse(ResponeCode.SUCCESS);
        }catch (Exception e){
            e.getMessage();
            return new APIResponse(ResponeCode.FAIL,e.getMessage());
        }
    }

Service

	@Override
    public void stopAutoRun(String id) {
        InterfaceManagement management = managementMapper.selectById(id);
        for (Map.Entry<String, Timer> entry : timerMap.entrySet()) {
            Timer timer = entry.getValue();
            //根据之前存储的全局Map获取name然后去除定时任务
            if (id.equals(entry.getKey())) {
                timer.cancel();
                timerMap.remove(entry.getKey());
            }
        }
        management.setAutoRun("0");
        management.setThreadName("");
        managementMapper.updateById(management);
        for (Thread thread : Thread.getAllStackTraces().keySet()) {
            //强制停止线程
            if (thread.getName().equals(management.getThreadName())) {
                thread.stop();
            }
        }
    }

项目启动初始化任务启动状态

CommandLineRunner

package diit.resourcemanage.config;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import diit.resourcemanage.mapper.InterfaceManagementMapper;
import diit.resourcemanage.model.po.InterfaceManagement;
import diit.resourcemanage.service.impl.InterfaceManagementServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.List;
//通过实现CommandLineRunner然后重写run来使服务启动完成后对启动状态初始化
@Component
public class InterfaceManagementInitConfig implements CommandLineRunner {

    @Autowired
    private InterfaceManagementMapper managementMapper;
    @Autowired
    private InterfaceManagementServiceImpl interfaceManagementService;

    @Override
    public void run(String... args) throws Exception {
        QueryWrapper<InterfaceManagement> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("auto", "1");
        List<InterfaceManagement> managementList = managementMapper.selectList(queryWrapper);
        if (managementList.size() != 0){
            for (InterfaceManagement management : managementList) {
                management.setAutoRun("0");
                management.setThreadName("");
            }
        }
        interfaceManagementService.updateBatchById(managementList);
    }
}

posted @ 2022-09-08 13:12  Ideaway  阅读(426)  评论(0)    收藏  举报