|
@@ -0,0 +1,181 @@
|
|
|
|
|
+package com.github.microservice.core.util.queue;
|
|
|
|
|
+
|
|
|
|
|
+import com.github.microservice.core.util.os.SystemUtil;
|
|
|
|
|
+import lombok.*;
|
|
|
|
|
+import lombok.experimental.Accessors;
|
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.springframework.util.Assert;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.concurrent.CountDownLatch;
|
|
|
|
|
+import java.util.concurrent.Executors;
|
|
|
|
|
+import java.util.concurrent.ScheduledExecutorService;
|
|
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
+
|
|
|
|
|
+@Slf4j
|
|
|
|
|
+public class ExecuteQueueUtil {
|
|
|
|
|
+
|
|
|
|
|
+ private static ScheduledExecutorService executorService = Executors.newScheduledThreadPool(SystemUtil.getCpuCoreCount() * 2);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ static {
|
|
|
|
|
+ Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
|
|
|
|
+ executorService.shutdownNow();
|
|
|
|
|
+ }));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @SneakyThrows
|
|
|
|
|
+ public static <T> T execute(int maxTryCount, SleepTime sleepTime, Handle<T> handle) {
|
|
|
|
|
+ Assert.state(maxTryCount > 0, "最大执行次数必须大于0");
|
|
|
|
|
+ Assert.notNull(sleepTime, "休眠时间不能为空");
|
|
|
|
|
+ Assert.notNull(handle, "处理器不能为空");
|
|
|
|
|
+
|
|
|
|
|
+ final long startTime = System.currentTimeMillis();
|
|
|
|
|
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
|
|
|
|
|
+ final Item<T> item = new Item<T>() {{
|
|
|
|
|
+ setMaxTryCount(maxTryCount);
|
|
|
|
|
+ setStartTime(startTime);
|
|
|
|
|
+ setSleepTime(sleepTime);
|
|
|
|
|
+ setCountDownLatch(countDownLatch);
|
|
|
|
|
+ setHandle(handle);
|
|
|
|
|
+ }};
|
|
|
|
|
+ sleepExecute(1, item);
|
|
|
|
|
+ countDownLatch.await();
|
|
|
|
|
+
|
|
|
|
|
+ return item.getResult().getData();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 延迟执行
|
|
|
|
|
+ private static <T> void sleepExecute(int index, Item<T> item) {
|
|
|
|
|
+ executorService.schedule(() -> {
|
|
|
|
|
+ try {
|
|
|
|
|
+ final RunTime runTime = new RunTime() {{
|
|
|
|
|
+ setIndex(index);
|
|
|
|
|
+ setStartTime(item.getStartTime());
|
|
|
|
|
+ }};
|
|
|
|
|
+ //记录结果
|
|
|
|
|
+ item.setResult(item.getHandle().execute(runTime));
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ log.error(e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 异步则退出阻塞
|
|
|
|
|
+ if (item.getResult().isAsync()) {
|
|
|
|
|
+ countDown(item.getCountDownLatch());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 完成则退出阻塞
|
|
|
|
|
+ if (item.getResult().isDone()) {
|
|
|
|
|
+ countDown(item.getCountDownLatch());
|
|
|
|
|
+ // 结束,不在执行循环
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (index < item.getMaxTryCount()) {
|
|
|
|
|
+ sleepExecute(index + 1, item);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ countDown(item.getCountDownLatch());
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ }, item.getSleepTime().get(index), TimeUnit.MILLISECONDS);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static void countDown(CountDownLatch countDownLatch) {
|
|
|
|
|
+ if (countDownLatch.getCount() > 0) {
|
|
|
|
|
+ countDownLatch.countDown();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Data
|
|
|
|
|
+ @AllArgsConstructor
|
|
|
|
|
+ @NoArgsConstructor
|
|
|
|
|
+ public static class Item<T> {
|
|
|
|
|
+ private int maxTryCount;
|
|
|
|
|
+ private long startTime;
|
|
|
|
|
+ private SleepTime sleepTime;
|
|
|
|
|
+ private Handle<T> handle;
|
|
|
|
|
+ private CountDownLatch countDownLatch;
|
|
|
|
|
+
|
|
|
|
|
+ //结果集
|
|
|
|
|
+ private Result<T> result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ @Data
|
|
|
|
|
+ @Builder
|
|
|
|
|
+ @NoArgsConstructor
|
|
|
|
|
+ @AllArgsConstructor
|
|
|
|
|
+ @Accessors(chain = true)
|
|
|
|
|
+ public static class Result<T> {
|
|
|
|
|
+ // 返回的数据
|
|
|
|
|
+ private T data;
|
|
|
|
|
+
|
|
|
|
|
+ // 是否异步
|
|
|
|
|
+ private boolean async;
|
|
|
|
|
+
|
|
|
|
|
+ //是否结束
|
|
|
|
|
+ private boolean done;
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // 休眠时间
|
|
|
|
|
+ public interface SleepTime {
|
|
|
|
|
+ long get(int index);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // 处理器
|
|
|
|
|
+ public interface Handle<T> {
|
|
|
|
|
+ Result<T> execute(RunTime runTime);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Data
|
|
|
|
|
+ @AllArgsConstructor
|
|
|
|
|
+ @NoArgsConstructor
|
|
|
|
|
+ public static class RunTime {
|
|
|
|
|
+ private int index;
|
|
|
|
|
+ private long startTime;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+// @SneakyThrows
|
|
|
|
|
+// public static void main(String[] args) {
|
|
|
|
|
+//
|
|
|
|
|
+// String a = execute(10, (index) -> {
|
|
|
|
|
+// return Map.of(1, 1000L, 2, 1000L, 3, 1000L, 4, 5000L).getOrDefault(index, 5000L);
|
|
|
|
|
+// }, (runTime) -> {
|
|
|
|
|
+// long time = System.currentTimeMillis() - runTime.getStartTime();
|
|
|
|
|
+// System.out.println("------------" + Thread.currentThread());
|
|
|
|
|
+// System.out.println(runTime.getIndex() + "," + time);
|
|
|
|
|
+//
|
|
|
|
|
+// //异常
|
|
|
|
|
+//// if (runTime.getIndex() >= 3) {
|
|
|
|
|
+//// throw new RuntimeException("模拟异常");
|
|
|
|
|
+//// }
|
|
|
|
|
+//
|
|
|
|
|
+//// if (runTime.getIndex() >= 5) {
|
|
|
|
|
+//// return new Result<String>().setData("放弃").setDone(true);
|
|
|
|
|
+//// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 时间异步
|
|
|
|
|
+// if (time > 3000) {
|
|
|
|
|
+// return new Result<String>().setData("异步线程继续").setAsync(true);
|
|
|
|
|
+// }
|
|
|
|
|
+//
|
|
|
|
|
+// // 次数模拟完成
|
|
|
|
|
+//// if (runTime.getIndex() >= 5) {
|
|
|
|
|
+//// return new Result<String>().setData("完成").setDone(true);
|
|
|
|
|
+//// }
|
|
|
|
|
+//
|
|
|
|
|
+//
|
|
|
|
|
+// return new Result<String>().setData("未完成");
|
|
|
|
|
+// });
|
|
|
|
|
+//
|
|
|
|
|
+//
|
|
|
|
|
+// System.out.println("结果: " + a);
|
|
|
|
|
+//
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+}
|