便捷的定时异步执行
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);
}
}