簡體   English   中英

如果程序在n秒后未返回任何內容,如何在Java中調用函數

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

我有一個這樣的功能:

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

在這種情況下,如果somemethodForLogin()花費的時間比預期的長,例如8秒,我想返回false或引發異常。 我怎樣才能做到這一點?

我在somemethodForLogin()之前添加了類似的內容:

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

但是,即使調用成功,也總是會涉及到這一點。

您可以使用compleable future來調用登錄名,然后使用超時來檢索結果:

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

上面的lambda是Supplier而不是Runnable

CompletableFuture的get方法記錄如下:

如有必要,最多等待給定時間以完成此將來,然后返回其結果(如果有)。
TimeoutException-如果等待超時

編輯:
上面使用CompletableFuture<Void>因為調用采用了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秒,然后就可以立即設置超時。 更不用說在執行業務任務的池中減少競爭。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM