2008-09-18 53 views
9

Tôi muốn đọc nội dung của URL nhưng không muốn "treo" nếu URL không phản hồi. Tôi đã tạo một BufferedReader sử dụng URL ...Làm cách nào để đặt thời gian chờ dựa vào BufferedReader dựa trên URLConnection trong Java?

URL theURL = new URL(url); 
URLConnection urlConn = theURL.openConnection(); 
urlConn.setDoOutput(true); 
BufferedReader urlReader = new BufferedReader(newInputStreamReader(urlConn.getInputStream())); 

... và sau đó bắt đầu vòng lặp để đọc nội dung ...

do 
    { 
    buf = urlReader.readLine(); 
    if (buf != null) 
     { 
     resultBuffer.append(buf); 
     resultBuffer.append("\n"); 
     } 
    } 
while (buf != null); 

... nhưng nếu đọc treo rồi ứng dụng bị treo.

Có cách nào, không xay mã xuống mức ổ cắm, để "hết thời gian" đọc nếu cần?

Trả lời

12

Tôi nghĩ URLConnection.setReadTimeout là những gì bạn đang tìm kiếm.

+2

Tuyệt vời, cảm ơn bạn. Đã thêm vào 1,5! – dacracot

2

Vì Java 1.5, có thể đặt thời gian chờ đọc theo mili giây trên ổ cắm bên dưới thông qua phương thức 'setReadTimeout (int timeout)' trên lớp URLConnection.

Lưu ý rằng cũng có 'setConnectTimeout (int timeout)' sẽ thực hiện tương tự cho kết nối ban đầu với máy chủ từ xa, vì vậy điều quan trọng là phải thiết lập điều đó.

+1

Không mởConnection() bắt đầu kết nối, vì vậy việc đặt thời gian chờ kết nối mở có hiệu lực hay không đọc giá trị ngay cả sau khi nó bắt đầu quá trình kết nối? – William

3

Nếu bạn có java 1.4:

tôi giả sử thời gian chờ kết nối (URLConnection.setConnectTimeout(int timeout)) là không sử dụng vì bạn đang làm một số loại trực tuyến.

--- Đừng diệt các sợi --- Nó có thể gây ra vấn đề không rõ, mô tả mở vv

đẻ trứng một java.util.TimerTask nơi bạn sẽ kiểm tra xem bạn đã hoàn thành quá trình này, cách khác, đóng BufferedReader và OutputStream của URLConnection

Chèn một lá cờ boolean isFinished và đặt nó vào đúng ở phần cuối của vòng lặp của bạn và false trước khi vòng lặp

TimerTask ft = new TimerTask(){ 
    public void run(){ 
    if (!isFinished){ 
     urlConn.getInputStream().close(); 
     urlConn.getOutputStream().close(); 
    } 
    } 
}; 

(new Timer()).schedule(ft, timeout); 

Điều này có thể sẽ gây ra hiện tượng ioexception, vì vậy bạn phải bắt nó. Ngoại lệ không phải là một điều xấu trong chính nó. Tôi bỏ qua một số khai báo (tức là trận chung kết) để lớp ẩn danh có thể truy cập các biến của bạn. Nếu không, sau đó tạo POJO duy trì một tham chiếu và chuyển nó tới timertask

+0

Đó là một giải pháp tốt đẹp, nhưng tôi nghĩ nhiệm vụ của bạn sẽ chỉ cháy một lần. Điều đó có thể sẽ thất bại trong một quá trình chuyển giao dài hạn, do đó sẽ tốt hơn nếu chạy trên một khoảng thời gian và dừng bộ hẹn giờ khi hoàn thành. Ý tưởng thú vị, mặc dù. – jsight

1

Tôi đã làm việc về vấn đề này trong môi trường JVM 1.4 gần đây. Câu trả lời chứng khoán là sử dụng các thuộc tính hệ thống sun.net.client.defaultReadTimeout (read timeout) và/hoặc sun.net.client.defaultConnectTimeout. Đây là những tài liệu tại Networking Properties và có thể được thiết lập thông qua -D đối số trên dòng lệnh Java hoặc thông qua một cuộc gọi phương thức System.setProperty.

Giả sử chúng được lưu trong bộ nhớ cache bởi quá trình triển khai, do đó bạn không thể thay đổi chúng từ thứ này sang vật khác để chúng được sử dụng một lần, các giá trị được giữ lại.

Ngoài ra, chúng không thực sự hoạt động đối với các kết nối SSL ala HttpsURLConnection. Có nhiều cách khác để xử lý bằng cách sử dụng SSLSocketFactory tùy chỉnh.

Một lần nữa, tất cả điều này áp dụng cho JVM 1.4.x. Tại 1.5 và ở trên bạn có nhiều phương pháp có sẵn cho bạn trong API (như được ghi nhận bởi các phản hồi khác ở trên).

1

Đối với Java 1.4, bạn có thể sử dụng SimpleHttpConnectionManager.getConnectionWithTimeout (hostConf, CONNECTION_TIMEOUT) từ Apache

Các vấn đề liên quan