• java 防止执行方法时阻塞:为方法设置运行时间,超时结束


    一、函数式方法

    import java.util.HashMap;
    import java.util.concurrent.*;
    import java.util.function.Supplier;
    
    /**
     * 设置一个方法运行超时时间,超时结束该方法
     * 缺陷:线程池shutdown结束不了死循环。
     */
    public class TimeOutShutdownMethod {
        /** 超时时间 **/
        private static final int TIMEOUT = 30;
        /** 超时时间单位 **/
        private static final TimeUnit TIMEOUT_UNIT = TimeUnit.SECONDS;
    
        /**
         * 设置方法的超时时间
         * @param increase 调用的方法
         * @return 调用方法的return值
         */
        public static Object setMethodShutdownTimeOut(Supplier<Object> increase) {
            return setMethodShutdownTimeOut(increase, TIMEOUT, TIMEOUT_UNIT);
        }
    
    
        /**
         * 设置方法的超时时间
         * @param increase 调用的方法
         * @param timeout 超时时间
         * @param timeUnit 超时时间单位
         * @return 调用方法的return值
         */
        public static Object setMethodShutdownTimeOut(Supplier<Object> increase, int timeout, TimeUnit timeUnit) {
            final ExecutorService exec = Executors.newFixedThreadPool(1);
            Callable call = () -> increase.get();
    
            Future<String> future = exec.submit(call);
            Object object = null;
            try {
                object = future.get(timeout, timeUnit);
                System.out.println("方法执行完成");
            } catch (Exception e) {
                // 方法超时
                System.out.println("方法执行失败");
            }
            exec.shutdownNow();
    
            return object;
        }
        
    
        public static void main(String[] args) {
            Supplier<Object> increase = () -> t("1", "2", 3);
            HashMap<String, Object> tt = (HashMap<String, Object>) setMethodShutdownTimeOut(increase, 5, TIMEOUT_UNIT);
            System.out.println(tt);
        }
    
        public static HashMap t(String a, String b, Integer c) {
            int aa = 1;
            while (true) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (aa ++ > 1) {
                    break;
                }
            }
            HashMap<String, Object> stringStringHashMap = new HashMap<>();
            stringStringHashMap.put(a, b);
            stringStringHashMap.put(b, c);
            return stringStringHashMap;
        }
    
    }

    二、反射实现

    import java.lang.reflect.Method;
    import java.util.HashMap;
    import java.util.concurrent.*;
    
    /**
     * 设置一个方法运行超时时间,超时结束该方法
     * 缺陷:方法参数不能是基础类型(利用反射但未传类型参数,只传参数值。参数值toClass会转成包装类)。线程池shutdown结束不了死循环。
     * */
    public class TimeOutShutdownMethod {
        private static final Logger logger = Logger.getLogger("TimeOutShutdownMethod.class");
        /** 超时时间 **/
        private static final int TIMEOUT = 30;
        /** 超时时间单位 **/
        private static final TimeUnit TIMEOUT_UNIT = TimeUnit.SECONDS;
    
        /**
         * 设置方法的超时时间
         * @param clazz 调用的方法所属的类
         * @param methodName 调用的方法
         * @param args 调用的方法参数
         * @return 调用方法的return值
         */
        public static Object setMethodShutdownTimeOut(Class clazz, String methodName, Object... args) {
            return setMethodTimeOut(clazz, methodName, TIMEOUT, TIMEOUT_UNIT, args);
        }
    
        /**
         * 设置方法的超时时间
         * @param clazz 调用的方法所属的类
         * @param methodName 调用的方法
         * @param timeout 超时时间
         * @param timeUnit 超时时间单位
         * @param args 调用的方法参数
         * @return 调用方法的return值
         */
        public static Object setMethodTimeOut(Class clazz, String methodName, int timeout, TimeUnit timeUnit, Object... args) {
            final ExecutorService exec = Executors.newFixedThreadPool(1);
    
            Callable call = () -> {
                Method method = clazz.getDeclaredMethod(methodName, toClass(args));
           method.setAccessible(true); Object invoke
    = method.invoke(clazz.newInstance(), args); return invoke; }; Future<String> future = exec.submit(call); Object object = null; try { object = future.get(timeout, timeUnit); System.out.println("方法执行完成"); } catch (Exception e) { // 方法超时 System.out.println("方法执行失败"); logger.error("method exec timeout!!!", e); }      // 结束不了死循环 exec.shutdownNow(); return object; } private static Class<?>[] toClass(Object... args) { Class<?>[] parameterTypes = new Class<?>[args.length]; for (int i=0; i < args.length; i++) { parameterTypes[i] = args[i].getClass(); } return parameterTypes; } public static void main(String[] args) { System.out.println("RRR: "); System.out.println(TimeOutShutdownMethod.setMethodTimeOut(TimeOutShutdownMethod.class, "t", 50, TimeUnit.SECONDS,"sr", "rr", 123)); } public static HashMap t(String a, String b, Integer c) { int aa = 1; while (true) { try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } if (aa ++ > 10) { break; } } HashMap<String, Object> stringStringHashMap = new HashMap<>(); stringStringHashMap.put(a, b); stringStringHashMap.put(b, c); return stringStringHashMap; } }
  • 相关阅读:
    TP5.1 遇见问题整理
    PDO 基础
    php7 连接 mysql 的两种方式
    [php] 添加接口访问日志(文件)
    curl 向远程服务器传输file文件
    VBoxManage
    linux 系统下安装多个php版本
    vim中文乱码问题
    vim 翻页命令
    php list()函数
  • 原文地址:https://www.cnblogs.com/day1day1up/p/15774471.html
Copyright © 2020-2023  润新知