2010-11-15 33 views
17

Tôi có một thread thực thi đoạn mã sau:Làm thế nào để dừng một chuỗi đang chờ trong một hoạt động đọc chặn trong Java?

public void run() { 
    try { 
     int n = 0; 
     byte[] buffer = new byte[4096]; 
     while ((n = in.read(buffer)) != -1) { 
      out.write(buffer, 0, n); 
      out.flush(); 
     } 
    } catch (IOException e) { 
     System.out.println(e); 
    } 
} 

nơi inSystem.in. Làm thế nào tôi có thể ngăn chặn chủ đề như vậy một cách duyên dáng? Không đóng System.in cũng như không sử dụng Thread.interrupt có vẻ như hoạt động.

+1

điều gì xảy ra khi bạn sử dụng ngắt? –

+0

@tulskiy: Chủ đề tiếp tục chạy cho đến khi nhấn Ctrl-D (EOF) theo cách thủ công. – vitaut

Trả lời

7

Điều này là do đọc System.in (InputStream) là một hoạt động chặn.

Look đây Is it possible to read from a InputStream with a timeout?

+1

Cảm ơn. Sử dụng NIO 'FileChannel' được trích xuất từ' System.in' cho phép dừng thread chỉ bằng cách đóng 'System.in'. Đóng các kết quả 'System.in' trong' AsynchronousCloseException' làm gián đoạn việc chặn 'FileChannel.read'. – vitaut

2

Bạn có thể sử dụng phương pháp có sẵn() (đó là non-blocking) để kiểm tra xem có bất cứ điều gì để đọc trước.

Trong pseudo-java:

//... 
while(running) 
{ 
    if(in.available() > 0) 
    { 
     n = in.read(buffer); 
     //do stuff with the buffer 
    } 
    else 
    { 
     Thread.sleep(500); 
    } 
} 
//when running set to false exit gracefully here... 
+1

Đang chờ 0,5 giây - điều đó có vẻ không đúng? – dacwe

+1

Số văn bản, nếu bạn không ngủ, bạn sẽ kết thúc trong một vòng quay nóng, CPU chờ các byte sẵn có để đọc. Giả định của tôi là chủ đề này sẽ dành phần lớn thời gian của nó chờ đợi cho đầu vào. – Paolo

+0

Sử dụng 'available' gần như không phải là thủ thuật. Vấn đề là trong trường hợp EOF 'available' trả về 0 và chuỗi tiếp tục thực hiện. 1 để bù đắp cho không công bằng -1 =) – vitaut

-3

bạn có thể sử dụng một lá cờ bên ngoài cho điều này

boolean flag = true; 


public void run() { 
    try { 
     int n = 0; 
     byte[] buffer = new byte[4096]; 
     while ((n = in.read(buffer)) != -1 && flag) { 
      out.write(buffer, 0, n); 
      out.flush(); 
     } 
    } catch (IOException e) { 
     System.out.println(e); 
    } 
} 
+3

Điều đó sẽ không làm gián đoạn cuộc gọi đã chặn, do đó, nó không giải quyết được sự cố. –

0

Nếu bạn muốn cung cấp cho người dùng một thời gian để nhập dữ liệu - có thể cho phép trọng giá trị mặc định hoặc gián đoạn một số quy trình tự động -, sau đó đợi trước và kiểm tra đầu vào có sẵn sau khi tạm dừng:

System.out.println("Enter value+ENTER within 5 Seconds to override default value: "); 
try{ 
    Thread.sleep(5000); 
} catch {InterruptedException e){} 

try{ 
    int bytes = System.in.available(); 
    if (bytes > 0) { 
    System.out.println("Using user entered data ("+size+" bytes)"); 
    } else { 
    System.out.println("Using default value"); 
    } 
} catch(IOException e) { /*handle*/ } 
6

Bạn đã tình cờ gặp một người 9 tuổi bug không ai sẵn sàng sửa chữa. Họ nói rằng có một số cách giải quyết trong this bug report. Hầu hết có thể, bạn sẽ cần phải tìm một số cách khác để thiết lập thời gian chờ (chờ đợi bận rộn dường như không thể tránh khỏi).

1

tôi đã cùng một vấn đề ngày hôm nay, và đây là cách tôi cố định nó, sử dụng in.ready():

public void run() { 
    String line; 
    // Some code 

    while(!Thread.currentThread().isInterrupted()){ 
     try { 
      if (in.ready()) { 
       line = in.readLine(); 
      } 
     } catch (Exception e) { 
      try { 
       Thread.currentThread().wait(500); 
      } catch (InterruptedException e1) { 
       // Do what we want when thread is interrupted 
      } 
     } 
    } 
} 
+0

Thú vị, nhưng không phải là nó lấy rất nhiều CPU bằng cách thực hiện vòng lặp tất cả các thời gian trong khi không có gì để đọc? – vitaut

+0

Trên thực tế đó là lý do tại sao tôi thực hiện các chủ đề chờ đợi một thời gian mỗi lần lặp. Nhưng bạn nói đúng, nó không hiệu quả như nó có thể. Nó phụ thuộc vào mục đích phần mềm là gì. – Nans

+1

Khá chắc chắn điều này vẫn bị treo nếu không có dòng mới trên luồng. in.ready() trả về true nếu có một byte đơn, in.readLine() đọc nó, sau đó tiếp tục chờ (mãi mãi) cho dòng mới. – pendor

1

Có an toàn để đóng trong dòng trong chủ đề khác? Nó phù hợp với tôi. Trong trường hợp này, in.read(...) ném ngoại lệ SocketException.

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