简体   繁体   English

如果程序在n秒后未返回任何内容,如何在Java中调用函数

[英]How to call a function in java if the program doesn't return anything after n seconds

I have a function like this: 我有一个这样的功能:

public boolean doLogin() {
    try {
        somemethodForLogin();
        return true;
    }  catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

In this case I want to return false or throw an exception if somemethodForLogin() takes more time than expected, say 8 seconds. 在这种情况下,如果somemethodForLogin()花费的时间比预期的长,例如8秒,我想返回false或引发异常。 How can I do this? 我怎样才能做到这一点?

I added something like this just before somemethodForLogin() : 我在somemethodForLogin()之前添加了类似的内容:

new java.util.Timer().schedule(
    new java.util.TimerTask() {
        @Override
        public void run() {
            System.out.println("Returning after 8 seconds wait");
        }
    }, 8000);

But it comes into this always, even if the call is success. 但是,即使调用成功,也总是会涉及到这一点。

You can use a completable future to call the login, then retrieve the result with a timeout: 您可以使用compleable future来调用登录名,然后使用超时来检索结果:

try {
    CompletableFuture.runAsync(() -> somemethodForLogin())
                 .get(8, TimeUnit.SECONDS);
    return true;
}catch(TimeoutException timeoutException) {
    //Timeout handline here
    return false; //or call other function
}

The above lambda is a Supplier rather than a Runnable . 上面的lambda是Supplier而不是Runnable

CompletableFuture's get method is documented with the following: CompletableFuture的get方法记录如下:

Waits if necessary for at most the given time for this future to complete, and then returns its result, if available. 如有必要,最多等待给定时间以完成此将来,然后返回其结果(如果有)。
TimeoutException - if the wait timed out TimeoutException-如果等待超时

EDIT: 编辑:
The above is using CompletableFuture<Void> as the call is taking a Runnable . 上面使用CompletableFuture<Void>因为调用采用了Runnable If somemethodForLogin() returns a value, you can use the same API, but calling supplyAsync : 如果somemethodForLogin()返回一个值,则可以使用相同的API,但是要调用supplyAsync

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

So i have just created a sample program to solve your problem .I think that it works as expected but you could also tried it at your side. 因此,我刚刚创建了一个示例程序来解决您的问题。我认为它可以按预期工作,但是您也可以在您身边尝试它。

I have explained the code in the code comments so it is not a code dump. 我已经在代码注释中解释了代码,因此它不是代码转储。

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());

    }
}

Both answers allow a possibility for a denial of service attack by repeated login requests. 这两个答案都允许通过重复的登录请求拒绝服务攻击。 As the executing thread will still continue to execute after 8 seconds, firing repeated login attempts would keep creating threads that would eat away the resources. 由于执行线程将在8秒后仍继续执行,因此触发重复的登录尝试将继续创建将消耗资源的线程。 The CompletableFuture approach would fill up the common pool, which wouldn't keep creating threads, but it would affect every other part of the code that uses the common pool. CompletableFuture方法将填满公共池,该池不会继续创建线程,但是会影响使用公共池的代码的所有其他部分。

What you can do is create a secondary pool with one or just a few connections dedicated to logging in. Set the connection checkout timeout to 8 seconds, and you've got your timeout there right out of the box. 您可以做的是创建一个具有一个或几个仅用于登录的连接的辅助池。将连接签出超时设置为8秒,然后就可以立即设置超时。 Not to mention less competition on the pool that's doing business tasks. 更不用说在执行业务任务的池中减少竞争。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM