Java 如果程序没有';n秒后我不会返回任何内容

Java 如果程序没有';n秒后我不会返回任何内容,java,Java,我有这样一个函数: public boolean doLogin() { try { somemethodForLogin(); return true; } catch (Exception e) { e.printStackTrace(); return false; } } 在这种情况下,如果somemethodForLogin()花费的时间比预期的要多,比如说8秒,我想返回false或抛出异常。我

我有这样一个函数:

public boolean doLogin() {
    try {
        somemethodForLogin();
        return true;
    }  catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}
在这种情况下,如果
somemethodForLogin()
花费的时间比预期的要多,比如说8秒,我想返回
false
或抛出异常。我该怎么做

我在
somemethodForLogin()之前添加了类似的内容:


但是,即使调用成功,也总是会出现这种情况。

您可以使用可完成的future来调用登录名,然后通过超时检索结果:

try {
    CompletableFuture.runAsync(() -> somemethodForLogin())
                 .get(8, TimeUnit.SECONDS);
    return true;
}catch(TimeoutException timeoutException) {
    //Timeout handline here
    return false; //or call other function
}
上述lambda是
供应商
,而不是
可运行的供应商

CompletableFuture的
get
方法记录如下:

如果需要,最多等待给定的时间以完成此未来,然后返回其结果(如果可用)。
TimeoutException-如果等待超时

编辑:
上面使用的是
CompletableFuture
,因为调用采用的是
Runnable
。如果
somemethodForLogin()
返回一个值,则可以使用相同的API,但调用
supplyAsync

Object loginResult = CompletableFuture.supplyAsync(() -> somemethodForLogin())
        .get(8, TimeUnit.SECONDS);
//Just change the return types accordingly.

因此,我刚刚创建了一个示例程序来解决您的问题。我认为它可以按预期工作,但您也可以在您的身边尝试

我已经在代码注释中解释了代码,因此它不是代码转储

class Test
{
    // your do logic method 
    public boolean doLogic()
    {
        try{
            //New Thread for logic();
            Thread t1=new Thread(new Runnable() {
                        public void run() {
                            // calling your logic function in  a new thread
                            try{login();}catch(Exception e){e.printStackTrace();}
                        }
                    });
            t1.start();

            //Making the current thread to sleep for 8 seconds.
            Thread.sleep(8000);
            //check if t1 has ended  within 8 seconds, and then return the required value
            if(!t1.isAlive())
                return true;
            else
                return false;
        }
        catch(Exception e)
        {
            e.printStackTrace();
            return false;
        }
    }

    void login()throws Exception
    {
        Thread.sleep(9000);//tweak this value sleeps the t1 thread for a specific time just to simulate the login function
    }
    // driver method
    public static void main(String args[])
    {
        System.out.println(new Test().doLogic());

    }
}

这两种回答都允许通过重复登录请求进行拒绝服务攻击。由于执行线程在8秒后仍将继续执行,因此重复启动登录尝试将继续创建线程,从而消耗资源。
CompletableFuture
方法将填充公共池,这不会持续创建线程,但会影响使用公共池的代码的其他所有部分


您可以创建一个辅助池,其中包含一个或几个专用于登录的连接。将连接签出超时设置为8秒,您就可以立即获得超时。更不用说在执行业务任务的池中竞争会减少。

我想我们需要知道
somemethodForLogin()
实际上在做什么。如果它正在使用类似于
HttpURLConnection
的方法进行某种REST/web调用,则可以为该调用添加超时。在单独的线程中调用someMethodForLogin,如果someMethodForLogin尚未结束,则停止当前线程8秒,然后杀死该线程并返回false,否则返回true@javafan虽然这个解决方案听起来合乎逻辑,但实际上不起作用。@TimBiegeleisen somemethodForLogin()对我来说不是一个单独的函数,我将连接到mysql,比较那里的密码。有时,如果没有可用的连接,它将花费比预期更多的时间。在这种情况下,我想抛出一个正确的错误。听起来,你在试图解决错误的问题。如果连接不足,设置登录超时并不是明智之举。例如,您可以使用另一个较小的(或单个连接)池来执行身份验证,以确保连接始终可用itself@Jerry你仍然可以使用完全的未来。将编辑答案。虽然这是有效的,但它主要与问题无关。确实,在服务调用上设置连接和读取超时是第一件要做的事情,但是
somemethodForLogin
实际上是一个黑匣子,因此可能确实需要超时。@ErnestKiwele在“黑匣子”情况下,没有可靠的方法提供方法超时。这个答案基于OP对登录方法进行DB身份验证的评论。如果它执行套接字操作,我们可以使用套接字超时。如果它执行可中断的操作,我们可以调用
Thread.interrupt()
。太多的人建议有一个简单的解决方案(许多复制者建议使用
ExecutorService/Future
方法),但这样想不是一个好主意。这就像认为你不需要担心编码,因为它在你的计算机上工作。
class Test
{
    // your do logic method 
    public boolean doLogic()
    {
        try{
            //New Thread for logic();
            Thread t1=new Thread(new Runnable() {
                        public void run() {
                            // calling your logic function in  a new thread
                            try{login();}catch(Exception e){e.printStackTrace();}
                        }
                    });
            t1.start();

            //Making the current thread to sleep for 8 seconds.
            Thread.sleep(8000);
            //check if t1 has ended  within 8 seconds, and then return the required value
            if(!t1.isAlive())
                return true;
            else
                return false;
        }
        catch(Exception e)
        {
            e.printStackTrace();
            return false;
        }
    }

    void login()throws Exception
    {
        Thread.sleep(9000);//tweak this value sleeps the t1 thread for a specific time just to simulate the login function
    }
    // driver method
    public static void main(String args[])
    {
        System.out.println(new Test().doLogic());

    }
}