美文网首页
Java超时

Java超时

作者: 悟剑声 | 来源:发表于2019-06-22 12:35 被阅读0次

超时处理问题:在串行过程中,需要实现一个方法来执行某种任务,而这个方法的执行时间不能超过指定值,如果超时,则调用者不管这个方法将来是否可能执行成功,都要中断它的执行,或者让这个方法返回。

可以提出三种解决方案,一种同步的解决方案和两种异步的解决方案。

串行超时

串行超时处理是指程序只有一个线程,调用者调用任务方法,完全由执行任务的方法本身进行超时处理。

    public void runTask(long timeout){
            long beginTime=System.currentTimeMillis();
            while((System.currentTimeMillis()-beginTime<timeout)&&(任务返回判断)){
                  //执行循环体内的任务片段和算法
         }
    }

特点:

  • 该方案无法处理因阻塞引起的超时情况
  • 该方案不会引入新的线程

适用场景:

  • 任务需要循环执行多个任务,每个任务执行时间稳定或内部包含超时机制。项目中一般要把这样的片段放到最外层。

利用wait/notify实现异步超时处理

利用多线程机制实现任务方法的异步执行很简单,只需要创建一个类实现Runnable接口,把任务放在重写的run方法中,run方法即为处理任务的方法。在主线程中使用Thread类创建并启动新任务线程即可。
让主线程在启动任务线程之后进行带超时参数的wait操作,如果任务线程超时,则wait不再等待,wait返回后主动中断任务线程;如果在超时时间内任务线程执行完毕,则通过notify方法通知主线程,这样主线程的wait方法也可以返回。

class TaskThread implements Runnable
    @Override
    public void run(){
            //各种任务执行准备
            while((任务没有被要求停止)&&(任务本身的各种判断条件)){
                  //本次循环中的子任务处理
                  //包括各种可能的IO阻塞和挂起等待操作
            }
            synchronized(monitor){  //此处的monitor引用必须主线程中的monitor对象
                  monitor.notify()    //任务执行完毕,唤醒主线程的wait操作
            }
    }
}

public void caller(){
            Object monitor  = new Object();
            TaskThread task = new TaskThread();
            Thread thread   = new Thread(task);
            //对task对象进行各种set操作以初始化任务
            try{
                synchronized(monitor){
                    thread.start();
                    while(线程没有顺利完成){
                        monitor.wait(timeout);
                    }
                    //线程顺利结束,获取并处理结果
                }
            }catch(InterruptExceptione){
                //等待已经被超时或者其他原因中断,终止线程thread
            }finally{
                //进行资源回收等收尾工作
            }
}

利用Callable接口实现异步超时处理

为了去掉线程间的同步操作,以及能够让任务线程方法有返回值和抛出异常,可以使用Callable接口来替代Runnable接口,相应的主线程也需要相应变动。
Callable接口位于java.utils.concurrent包中,其抽象方法call()有返回值,可以抛出异常。
调用Callable接口需要ExecutorService接口实例,而获取call方法的返回值需要Future接口实例。

class  TaskThread implements Callable{
    @Override
    public String call() throws AnyException{
        //各种任务执行准备
        while((任务没有被要求停止)&&(任务本身的各种判断条件)){
            //本次循环中的子任务处理
        //包括各种可能的IO阻塞和挂起等待操作
        }
    }
}

public void caller() throws InterruptedExceptio,TimeoutExceptio,ExecutorException{
    TaskThread task=new TaskThread();   //实现Callable接口的任务线程类
    ExecutorService exec=Executors.newFixedThreadPool(1);
    //对task对象进行各种set操作以初始化任务
    Future<String> future=exec.submit(task);
    try{
        return future.get(this.timeout,TimeUnit.MILLISECONDS);
    }finally{
        if(任务线程没有顺利结束){
            //终止线程task
        }
        exec.shutdownNow();
    }
}

链接

相关文章

网友评论

      本文标题:Java超时

      本文链接:https://www.haomeiwen.com/subject/gagbtqtx.html