执行方法超时工具类

package com.doke.utils;

import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import java.util.Random;
import java.util.concurrent.*;
import java.util.function.Supplier;

/**
 * TimeoutUtil <br>
 *
 * @author doker
 * @date 2021/05/12
 */

@Slf4j
@Component
@NoArgsConstructor
public class ExecuteTimeoutUtil {

    private final ExecutorService executorService = Executors.newFixedThreadPool(3);

    @PreDestroy
    private void destroy() {
        executorService.shutdown();
    }

    /**
     * 有超时限制的方法
     *
     * @param bizSupplier 业务函数
     * @param timeout   超时时间,ms
     * @return 返回值
     */
    public <R> Result<R> executeTimeout(Supplier<R> bizSupplier, int timeout) {
        return executeTimeout(bizSupplier, null, timeout);
    }

    /**
     * 有超时限制的方法
     *
     * @param bizSupplier  业务函数
     * @param defaultResult 默认值
     * @param timeout    超时时间,ms
     * @return 返回值
     */
    public <R> Result<R> executeTimeout(Supplier<R> bizSupplier, R defaultResult, int timeout) {

        R result;
        String msg = "ok";
        FutureTask<R> futureTask = new FutureTask<>(bizSupplier::get);
        executorService.execute(futureTask);
        try {
            result = futureTask.get(timeout, TimeUnit.MILLISECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            msg = String.format("execute time out %d ms force end", timeout);
            log.error(msg, e);
            futureTask.cancel(true);
            result = defaultResult;
        }
        return of(result, msg);
    }

    /**
     * 随机耗时的测试方法
     */
    private String randomSpentTime() {
        Random random = new Random();
        int time = (random.nextInt(10) + 1) * 1000;
        log.info("execute method expect spent time : " + time + "ms");
        try {
            Thread.sleep(time);
        } catch (Exception e) {
        }
        return "randomSpentTime --> " + time;
    }

    public static void main(String[] args) throws Exception {

        ExecuteTimeoutUtil executeTimeoutUtil = new ExecuteTimeoutUtil();
        for (int i = 1; i <= 10; i++) {
            log.info("\n sequence: {} time out", i);
            Thread.sleep(6000);
            long start = System.currentTimeMillis();
            String result = executeTimeoutUtil.executeTimeout(() -> executeTimeoutUtil.randomSpentTime(), 5000).getOrElse("默认");
            log.info("fact spend time {} ms,result:{}", System.currentTimeMillis() - start, result);
        }
        executeTimeoutUtil.executorService.shutdown();
    }

    class Result<T>{
        private T data;
        private String msg;

        public Result(T data, String msg) {
            this.data = data;
            this.msg = msg;
        }

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public T getOrElse(T value) {
            return this.data = value;
        }



        @Override
        public String toString() {
            return "Result{" +
                    "data=" + data +
                    ", msg='" + msg + '\'' +
                    '}';
        }

    }

    public <T> Result<T> of(T result, String msg) {

        return new Result<>(result, msg);

    }

}

 

posted @ 2021-05-12 22:48  xxxxxxxxxxxxxxxd  阅读(140)  评论(0)    收藏  举报