【JAVA使用笔记】—— 自定义方法的超时控制

说明

本文介绍的是利用Java 并发工具箱concurrent包,实现对指定类中指定方法的执行时间的控制。

存在于 java.util.concurrent 包里的 ExecutorService 实现就是一个线程池的实现,包里定义了三个Executor接口:

        a. Executor:一个运行新任务的简单接口。

        b. ExecutorService:扩展了Executor接口。添加了一些用来管理执行器生命周期和任务生命周期的方法。

        c. ScheduledExecutorService:扩展了ExecutorService。支持Future和定期执行任务。

Java的线程池有四种:

        a. newCachedThreadPool —— 可缓存线程池,若线程池长度超过处理需要,则回收空线程,否则创建新线程,线程规模可无限大。且若当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

        b. newFixedThreadPool —— 定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。

// t_num 最大线程数
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(t_num);

        c. newScheduledThreadPool —— 定长线程池,支持定时的及周期性的任务执行,类似Timer。

// t_num 最大线程数(int)
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(t_num);

// 第一个参数是一个Runnable
// time_delay 延时时间(int)
// time_cycle 执行周期时间(int)
// 最后一个就是时间单位啦
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        // 执行方法
    }
}, time_delay, time_cycle, TimeUnit.xxx);

// 意思就是延迟time_delay秒后每time_cycle秒执行一次。

        d.   newSingleThreadExecutor —— 单线程 的线程池,支持FIFO, LIFO, 优先级策略。

 

接下来需要说明的就是Callable和Future

创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口。这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果。如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦。而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。在线程池提交Callable任务后返回了一个Future对象,使用它可以知道Callable任务的状态和得到Callable返回的执行结果。Future提供了get()方法让我们可以等待Callable结束并获取它的执行结果。

 

代码

public class TimeOutUtil {
    private long timeout;        // 超时时间
    private ExecutorService exec;
    private Callable call;
    private Future future;

    // 构造方法,我们需要初始化超时时间和最大线程数
    public TimeOutUtil(long timeout,int nMethod) {
        this.timeout = timeout;
        this.exec = Executors.newFixedThreadPool(nMethod);
    }

    // 监控方法
    // 参数(指定方法,指定类,方法的参数)
    // 返回方法执行的结果“正常结果”或“超时”或“其他异常”
    public Object checkTimeOut(Method method, Object theObj,Object param){
        System.out.println("LOG : get method "+method.getName());
        try {
            this.call = new Callable() {
                @Override
                public Object call() throws Exception {
                    if(null != param) {
                        return method.invoke(theObj, param);
                    }
                    else
                        return method.invoke(theObj,null);
                }
            };
            this.future = this.exec.submit(this.call);
            Object result = future.get(this.timeout, TimeUnit.MILLISECONDS);

            // 这里做了一下处理,如果方法是一个void就变成Boolean
            if(method.getReturnType() == void.class)
                return true;
            return result;
        } catch (TimeoutException e){
            System.out.println("ERROR : TimeOut");
            if(method.getReturnType() == Boolean.class||
                    method.getReturnType() == void.class)
                return false;
            else return null;
        } catch (Exception e){
            e.printStackTrace();
            return null;
        }

    }

    // 关闭
    public void shutdown(){
        if(!this.exec.isShutdown())
            this.exec.shutdown();
    }
}

使用

// 初始化
TimeOutUtil timeOutUtil = new TimeOutUtil(timeout,t_num);

// T 方法返回类型
// TheClass 指定类
// methodName 方法名
// params_type 方法参数类型
// params 方法参数
T rel =  (T)timeOutUtil
            .checkTimeOut(TheClass.class.getMethod(methodName,params_type),
                          this,
                          params);

// 别忘了关
timeOutUtil.shutdown();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值