2010-05-10 159 views
91

我想要返回false如果URL需要超過5秒的連接 - 這怎麼可能使用Java?下面是我使用的檢查網址是否有效HttpURLConnection超時設置

HttpURLConnection.setFollowRedirects(false); 
HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); 
con.setRequestMethod("HEAD"); 
return (con.getResponseCode() == HttpURLConnection.HTTP_OK); 

回答

153

HttpURLConnectionsetConnectTimeout方法的代碼。

超時正好被設置爲5000毫秒,再搭上java.net.SocketTimeoutException

你的代碼應該是這個樣子:

 

try { 
    HttpURLConnection.setFollowRedirects(false); 
    HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection(); 
    con.setRequestMethod("HEAD"); 

    con.setConnectTimeout(5000); //set timeout to 5 seconds 

    return (con.getResponseCode() == HttpURLConnection.HTTP_OK); 
} catch (java.net.SocketTimeoutException e) { 
    return false; 
} catch (java.io.IOException e) { 
    return false; 
} 

 
+1

我將該值設置爲10分鐘。然而,在2分鐘之前,它會拋出一個'java.net.ConnectException:Connection超時:connect'。你知道是什麼導致了這個問題? – Pacerier 2012-02-03 10:16:32

+0

@dbyrne這對我來說似乎有點困惑 - 因爲我們在創建HttpURLConnection對象後設置了超時時間,所以我想知道代碼中引發'SocketTimeoutException'的確切位置是什麼? – Less 2013-07-24 16:57:36

+3

SocketTimeoutException是IOException的子類。如果兩個catch塊都執行相同的操作,則可以捕獲IOException。 – spaaarky21 2013-12-05 22:27:01

85

您可以設置超時這樣,

con.setConnectTimeout(connectTimeout); 
con.setReadTimeout(socketTimeout); 
+1

什麼是我們可以指定的超時的最大值? – Pacerier 2012-02-03 10:16:48

+5

@Pacerier文檔沒有明確說明這一點。如果值爲負數(值爲0意味着無限期地等待),它會拋出IllegalArgumentException異常。由於超時是一個無符號的32位整數,我想最大超時大概是49天(儘管我嚴重懷疑這個值對任何人都有幫助)。 – 2012-10-25 07:17:06

+1

+1爲多種類型的超時... – jsh 2012-12-26 16:54:19

1

如果HTTP連接不超時,你可以在後臺線程本身(AsyncTask,Service等)中實現超時檢查器,下面的類是考試PLE爲自定義的AsyncTask其一定時期

public abstract class AsyncTaskWithTimer<Params, Progress, Result> extends 
    AsyncTask<Params, Progress, Result> { 

private static final int HTTP_REQUEST_TIMEOUT = 30000; 

@Override 
protected Result doInBackground(Params... params) { 
    createTimeoutListener(); 
    return doInBackgroundImpl(params); 
} 

private void createTimeoutListener() { 
    Thread timeout = new Thread() { 
     public void run() { 
      Looper.prepare(); 

      final Handler handler = new Handler(); 
      handler.postDelayed(new Runnable() { 
       @Override 
       public void run() { 

        if (AsyncTaskWithTimer.this != null 
          && AsyncTaskWithTimer.this.getStatus() != Status.FINISHED) 
         AsyncTaskWithTimer.this.cancel(true); 
        handler.removeCallbacks(this); 
        Looper.myLooper().quit(); 
       } 
      }, HTTP_REQUEST_TIMEOUT); 

      Looper.loop(); 
     } 
    }; 
    timeout.start(); 
} 

abstract protected Result doInBackgroundImpl(Params... params); 
} 

針對此

public class AsyncTaskWithTimerSample extends AsyncTaskWithTimer<Void, Void, Void> { 

    @Override 
    protected void onCancelled(Void void) { 
     Log.d(TAG, "Async Task onCancelled With Result"); 
     super.onCancelled(result); 
    } 

    @Override 
    protected void onCancelled() { 
     Log.d(TAG, "Async Task onCancelled"); 
     super.onCancelled(); 
    } 

    @Override 
    protected Void doInBackgroundImpl(Void... params) { 
     // Do background work 
     return null; 
    }; 
} 
+0

創建一個新的循環線程是絕對沒有必要安排一個調用取消()。你可以在'onPreExecute()'的主線程中做到這一點。另外,如果您手動取消任務,則還應取消預定的呼叫以避免泄漏。 – BladeCoder 2015-09-30 07:44:43

+0

這裏指的是在doInBackground()中間取消AsyncTask,而不是在執行onPreExecute()時需要太多時間,同樣我想取消AsyncTask的這個實例,這需要花費太多時間並且保留其他的很多感謝您的反饋。 – 2015-09-30 12:03:20

+1

我覺得我的信息不夠清楚。我沒有說你應該取消onPreExecute(),我說你應該在onPreExecute()中創建Handler,並從主線程發佈延遲取消。這樣您將使用主線程作爲循環線程,並且當doInBackground()正在執行時,您當然可以取消AsyncTask,因爲主線程也與後臺線程同時運行。 – BladeCoder 2015-09-30 12:36:47

0

樣我能得到解決這樣類似的問題,另外一個簡單的線條

HttpURLConnection hConn = (HttpURLConnection) url.openConnection(); 
hConn.setRequestMethod("HEAD"); 

後超時我要求是知道響應代碼,並且只是獲取元信息就足夠了,而不是獲得完整的響應主體。

默認的請求方法是GET,那需要很多時間才能返回,最後拋出SocketTimeoutException。當我將請求方法設置爲HEAD時,響應非常快。