2010-12-14 15 views

Trả lời

6

Đề xuất của tôi sẽ là sử dụng HttpClient thay vì HttpUrlConnection. Đó là một thư viện tốt hơn ở nhiều khía cạnh.

Sau đó, bạn có thể sử dụng:

final SimpleHttpConnectionManager connectionManager = 
      new SimpleHttpConnectionManager(); 
final HttpClient client = new HttpClient(connectionManager); 

// ... and when it's time to close the connection from another thread 
connectionManager.shutdown(); 

Nếu bạn cần phải đóng nhiều kết nối trên nhiều chủ đề, bạn có thể tái sử dụng một ví dụ của HttpClient và đóng chúng lại tất cả trong một đi trong một thời trang tương tự:

static MultiThreadedHttpConnectionManager connectionManager = 
      new MultiThreadedHttpConnectionManager(); 
// HttpClient instance that can be shared across threads and create multiple connections 
static HttpClient client = new HttpClient(connectionManager); 

// ... and when it's time to close connections 
connectionManager.shutdown(); 
0

Bạn đã thử đóng InputStream của kết nối không đồng bộ từ một chuỗi khác không? Không chắc chắn nếu nó là đúng cách, nhưng nó hoạt động với ổ cắm vì vậy nếu Java sử dụng patter thiết kế tương tự ở đây nó có thể làm việc quá. Nhưng ngay cả khi nó hoạt động, tốt hơn tìm một xác nhận từ một số nguồn đáng tin cậy, mặc dù, vì nó có vẻ như làm việc nhưng đôi khi thất bại vì nó thường xảy ra với lập trình đa luồng.

EDIT

Rõ ràng, it doesn't work.

0

Bạn có thể đọc đoạn dữ liệu theo đoạn (thông thường bạn nên làm theo cách đó) và kiểm tra cờ boolean được đặt thành true (chỉ báo dừng) từ chuỗi khác (xem xét sử dụng volatile). Ở đây vấn đề có thể là nếu đọc chunk mất quá lâu và nó sẽ chờ cho đoạn được đọc trước khi kiểm tra cờ. Tôi không chắc rằng việc đóng kết nối từ một luồng khác là một ý tưởng hay (mặc dù không có nguồn thông tin). Nhưng nếu bạn làm điều này, bạn có thể sử dụng một lá cờ để phân biệt các lỗi kết nối thực sự khi dừng.

+0

Thực tế, việc đọc một đoạn có thể mất vĩnh viễn nếu có sự cố với máy chủ hoặc với mạng. Vâng, nếu SO_KEEPALIVE được sử dụng thì nó có thể sẽ hết thời gian trong 15 phút hoặc lâu hơn, nhưng không phải luôn luôn và đó là bất hợp lý dài anyway. Sử dụng timeout có thể giúp, nhưng sau đó một lần nữa - thời gian chờ ngắn có thể gây ra báo động sai (và gây ra getInputStream() để thất bại, xem liên kết trong "không trả lời" của tôi) và thời gian chờ dài có thể giới thiệu độ trễ không cần thiết. –

3

Bạn có thể sử dụng InterruptedException kết hợp với Task/Executors. Chủ đề sinh ra của bạn sẽ có thể bắt được InterruptedException bằng cách gói lệnh try/catch xung quanh phương thức HttpURLConnection đang thực hiện việc tải xuống. Java Concurrency Trong thực tế, chương 6 và 7 có liên quan. Đặc biệt 7.2 "Dừng dịch vụ dựa trên luồng".

+2

Nhưng theo như tôi biết, I/O chặn "cũ" không hỗ trợ InterruptedException, chỉ có NIO. –

+2

Có, phương thức read() không hỗ trợ ngắt. – fhucho

0

tôi giả sử bạn không có quyền truy cập vào các dòng đầu vào hoặc nếu không bạn chỉ có thể đóng nó Nếu không được điều tiếp theo tốt nhất để làm là chỉ cần thiết lập các ưu tiên chủ đề 0

này sẽ giảm thiểu số lát thời gian được phân bổ cho luồng đó.

+0

Tôi đã đưa ra một liên kết trong câu trả lời của tôi giải thích rằng việc đóng InputStream không hoạt động. –

1

Tôi có thể nhận được close() trên InputStream để thực hiện trả lại read().

Tôi nhận thấy mã này thật khủng khiếp. Nó có hiệu quả bắt đầu một máy chủ lắng nghe trên cổng 32323 cho một kết nối HTTP. Sau đó nó sẽ đọc tất cả các dữ liệu có sẵn cho nó và ghi dữ liệu không có thật cho đến khi khách hàng có thể lấy được một InputStream. Khi khách hàng có thể lấy luồng đầu vào, máy chủ sẽ ngừng ghi dữ liệu mô phỏng tải xuống bị hỏng.

Đây là một ví dụ tầm thường mà nó có thể không hoạt động trong kịch bản thế giới thực của bạn.

Khách hàng sau đó đóng luồng bằng InputStream.close() làm cho số InputStream.read() bị ném.

public class Main { 

public static void main(String[] args) throws Exception { 

    final Object lock = new Object(); 
    final boolean test[] = new boolean[1]; 

    Thread thread = new Thread(new Runnable() { 

     public void run() { 
      try { 
       ServerSocket server = new ServerSocket(32323); 
       Socket socket = server.accept(); 
       System.out.println("New client"); 
       InputStream is = socket.getInputStream(); 
       OutputStream os = socket.getOutputStream(); 
       while (true) { 
        is.read(); 
        ///System.out.println(is.read()); 
        if (!test[0]) { 
         os.write(0); 
        } else { 
         synchronized (lock) { 
          lock.notifyAll(); 
         } 
        } 
       } 
      } catch (IOException ex) { 
       throw new RuntimeException(ex); 
      } 
     } 
    }); 
    thread.start(); 

    final InputStream[] asyncStream = new InputStream[1]; 

    Thread thread2 = new Thread(new Runnable() { 

     public void run() { 
      try { 
       URL url = new URL("http://localhost:32323"); 
       HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
       InputStream is = connection.getInputStream(); 
       System.out.println("got input stream"); 
       asyncStream[0] = is; 
       test[0] = true; 
       while (true) { 
        System.out.print("read start"); 
        is.read(); 
        System.out.println(" done"); 
       } 
      } catch (IOException ex) { 
       throw new RuntimeException("Read failed",ex); 
      } 
     } 
    }); 
    thread2.start(); 
    // wait enough time for data to run out 
    synchronized (lock) { 
     lock.wait(); 
    } 
    System.out.println("Closing connection"); 
    asyncStream[0].close(); 
    System.out.println("Connection closed"); 
} 

Output

New client 
got input stream 
read start done 
read start done 
read start done 
read start done 
read start done 
read start done 
read startClosing connection 
done 
read startRead failed 
Connection closed 
+0

Andrew, tôi nghĩ rằng bạn có thể đóng kết nối ngay sau khi đọc() nhưng trước khi System.out.println ("thực hiện") –

+0

-1 cho xử lý ngoại lệ dodgy, ngay cả trong mã mẫu – artbristol

+0

@artbristol tôi cho rằng ít hơn trong vài trường hợp. Câu trả lời được chấp nhận không có bất kỳ xử lý ngoại lệ nào. Tôi đã viết điều này hai năm trước và không nhớ ý định ban đầu nhưng tôi cho rằng nó là để hiển thị một phương pháp không phải là cách để xử lý ngoại lệ chính xác. –

0

InputStream.close() thể không làm việc, nhưng bạn đã thử HttpURLConnection.disconnect()? Nếu tôi không quá sai, nó sẽ buộc ngắt kết nối và do đó InputStream.read() phải trả về -1. Bạn nên chắc chắn kết nối lại trước khi tiếp tục.

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