异步任务工具类,并发工具类,可执行多个子任务,并等待执行结果
异步任务工具类,并发工具类
针对并发编程来说,执行任务的时候可以拆分子任务的时候就,尽量拆分子任务
例如:多连表查询的时候 不使用连表SQl 就可以使用
工具类代码
//package
import com.lsmy.bi.base.exception.CommonException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicReference;
/**
* v2
* @author wei
* @date 2022/8/3 15:30
* @TODO 异步线程信息共享
*/
@Slf4j
public class AsyncUtil {
private static final ThreadPoolTaskExecutor executor;
static {
executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(Integer.MAX_VALUE);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("Executor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
}
private final Map<String, Boolean> currentFuture;
public AsyncUtil() {
this.currentFuture = new HashMap<>();
}
/**
* 异步执行任务,无返回结果
*/
public void execute(Runnable task){
executor.execute(task);
}
/**
* 异步执行任务,有返回结果
*/
public <T> AtomicReference<T> submit(Callable<T> task){
try {
NodeAtomicReference<T> reference = new NodeAtomicReference<>();
currentFuture.put(reference.getUuid(), false);
executor.execute(()->{
try {
reference.getReference().set(task.call());
} catch (Exception e) {
log.info(e.getMessage(), e);
}
currentFuture.put(reference.getUuid(), true);
});
return reference.getReference();
} catch (Exception e) {
throw new CommonException(e.getMessage());
}
}
//等待所有异步任务完成
public void await(){
try {
waitFutureGetResult();
} catch (Exception e) {
log.error("线程等待执行完成异常=>" + e.getMessage(), e);
}
}
/**
* 等待所有任务获取到结果
*/
private void waitFutureGetResult(){
try {
TimeUnit.MILLISECONDS.sleep(10);
for (Map.Entry<String, Boolean> entry : currentFuture.entrySet()) {
if (!Boolean.TRUE.equals(entry.getValue())) {
waitFutureGetResult();
}
}
} catch (InterruptedException e) {
log.info(e.getMessage());
}
}
public void destroy() {
executor.destroy();
}
static class NodeAtomicReference<T>{
private final AtomicReference<T> reference;
private final String uuid;
public NodeAtomicReference() {
this.reference = new AtomicReference<>();
this.uuid = UUID.randomUUID().toString();
}
public AtomicReference<T> getReference() {
return reference;
}
public String getUuid() {
return uuid;
}
}
}
单元测试
//package
import com.lsmy.bi.DigitalScreenApplication;
import com.lsmy.bi.digital.screen.utils.AsyncUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.web.client.RestTemplate;
import java.util.concurrent.atomic.AtomicReference;
/**
* @Author wei
* @Date 2022/8/30 15:28
*/
@Slf4j
@SpringBootTest(classes = DigitalScreenApplication.class)
@ActiveProfiles("dev")
public class AsyncUtilTest {
@Test
public void syncTest(){
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://www.baidu.com/", String.class);
logPrint(String.valueOf(responseEntity.getBody()));
int ic = 0;
for (int i = 0; i < 1000; i++) {
ic += i;
}
logPrint(ic);
}
@Test
public void asyncTest() {
AsyncUtil asyncUtil = new AsyncUtil();
AtomicReference<String> body = asyncUtil.submit(() -> {
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://www.baidu.com/", String.class);
return responseEntity.getBody();
});
AtomicReference<Integer> body1 = asyncUtil.submit(() -> {
int ic = 0;
for (int i = 0; i < 1000; i++) {
ic += i;
}
return ic;
});
asyncUtil.await();
asyncUtil.destroy();
logPrint(body.get());
logPrint(body1.get());
}
private static void logPrint(Object resultObj) {
String result = String.valueOf(resultObj);
log.info("任务执行结果: " + result.substring(0, result.length() > 1000 ? 1000 : result.length() - 1));
}
}
执行结果
2022-12-05 17:10:13.176 INFO 7712 --- [ main] c.test.AsyncUtilTest : 任务执行结果: <!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>ç™¾åº¦ä¸€ä¸‹ï¼Œä½ å°±çŸ¥é“</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus></span><span class="bg s_btn_wr"><input ty
2022-12-05 17:10:13.176 INFO 7712 --- [ main] c.test.AsyncUtilTest : 任务执行结果: 49950