面试官:请你设计一个任务执行超时退出的接口!

文章目录

前言

这是蘑菇街一面面试官问我的一个问题。他说:如果有这么一个场景,我执行业务的时候,不想让业务执行时间超过一定时间,如果超出就停止执行,你怎么来设计!

思路

我们在学习Java并发编程的时候,那些常见的方法大多都有设置超时时间的参数,我们可以根据这一思路来设计超时结束任务的方案。我这里用到的是Thread.join()方法,先来解释下join方法吧。

join()方法:如果一个线程A执行了thread.join()语句,其含义是:当前线程A等待thread线程终止之后才从thread.join()返回。线程Thread除了提供join()方法之外,还提供了join(long millis)和join(long millis,int nanos)两个具备超时特性的方法。这两个超时方法表示,如果线程thread在给定的超时时间里没有终止,那么将会从该超时方法中返回。摘自《Java并发编程的艺术》

我们来看下join的源码:

public final synchronized void join(long millis)
throws InterruptedException {
    
    
    long base = System.currentTimeMillis();
    long now = 0;

    if (millis < 0) {
    
    
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) {
    
    
        while (isAlive()) {
    
    
            wait(0);
        }
    } else {
    
    
    	//正常来说,我们会进入到这里,进入到循环里,直到调用join方法的线程执行完毕之后或者超出时间限制了,才退出。
        while (isAlive()) {
    
    
            long delay = millis - now;
            if (delay <= 0) {
    
    
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

其实我感觉书中对join的解释还是有那么一点欠缺的,我认为是:当在主线程A中调用另一个线程B的join方法意味着,从一开始的A、B两个线程并发执行变为串行执行的了,也就是将B线程插入到A线程中,然后等待B线程执行完成以后,再执行剩下的A线程的任务了。如果这个join方法带有超时参数的话,可以理解为,在这段时间内,A等待B线程执行(串行),一旦超出这个时间,两个线程又会回到并发执行的状态了。

回到我们之前的问题 ,我们想设计一个超时退出的接口,就可以利用这个带有超时参数的join来实现,来看看我的代码,注意看注释。

package com.markus.basic.Java多线程.方法超时问题;
/**
 * Author:markusZhang
 * Date:Create in 2020/10/8 12:57
 * todo:
 */
public class JoinDemo {
    
    
    public static void main(String[] args){
    
    
        Thread method = new Thread(new ThreadMethod());
        //调用方法
        method.start();
        try {
    
    
            method.join(2000);//规定业务接口执行不能超过的时长
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
        method.interrupt();//调用中断很重要,如果不调用的话,就会回到上面说的,两个线程并发执行,就起不到效果了。
    }
}
class ThreadMethod implements Runnable{
    
    

    @Override
    public void run() {
    
    
        try {
    
    
            Thread.sleep(3000);//执行业务
            System.out.println("方法调用完成");
        } catch (InterruptedException e) {
    
    
            //e.printStackTrace();
            System.out.println("方法调用超时");
        }
    }
}

总结

当然了,设计任务执行超时退出有很多种方案,这个只是其中一种。在开发中,我们需要多注意下那些带有超时参数的方法,说不定也是可以设计的。

猜你喜欢

转载自blog.csdn.net/MarkusZhang/article/details/108962257