2009-06-21 42 views
30

Tôi đang sử dụng java.util.concurrent.Semaphore trong một dự án sở thích. Nó được sử dụng trong lớp kết nối mà tôi đang viết. Tôi có thể sử dụng nó với ít phiền toái, ngoại trừ phương pháp này:Tôi có phải lo lắng về InterruptedExceptions nếu tôi không làm gián đoạn bất cứ điều gì bản thân mình?

public void acquire(int permits) throws InterruptedException 

buộc tôi phải xử lý InterruptedException. Bây giờ, tôi không chắc chắn những gì "gián đoạn" một Thread thậm chí có nghĩa là và tôi không bao giờ làm điều đó (tốt, không rõ ràng anyway) trong mã của tôi. Điều này có nghĩa là tôi có thể bỏ qua ngoại lệ? Tôi nên xử lý nó như thế nào?

Trả lời

1

Chủ đề có thể bị gián đoạn bằng cách gọi Thread.interrupt(). Nó được sử dụng để báo hiệu một luồng một cách duyên dáng mà nó nên làm một cái gì đó khác. Thông thường, nó gây ra các hoạt động chặn (ví dụ: Thread.sleep()) để trả về trước đó và ném InterruptedException. Nếu chuỗi bị gián đoạn, cờ sẽ được đặt trên đó. Cờ này có thể được truy vấn thông qua cuộc gọi Thread.isInterrupted().

Nếu bạn không sử dụng gián đoạn chuỗi và vẫn nhận được ngoại lệ này, bạn chỉ có thể thoát khỏi chuỗi của mình (và tốt nhất là ghi lại ngoại lệ).

Nói chung, tùy thuộc vào ứng dụng đa luồng của bạn.

0

Bạn nên thoát phương thức run() sau khi bạn đã thực hiện bất kỳ dọn dẹp nào theo yêu cầu của Chủ đề.
HTH

6

Không. InterruptedException chỉ được tạo nếu bạn tự ngắt đoạn của mình. Nếu bạn không tự mình sử dụng Thread.interrupt() sau đó tôi sẽ hoặc ném lại nó như một số loại "ngoại lệ bất ngờ" hoặc đăng nhập nó như là một lỗi và di chuyển trên. Ví dụ trong mã của tôi khi tôi buộc phải bắt InterruptedException và tôi không bao giờ gọi interrupt() bản thân mình, tôi làm tương đương với

catch (InterruptedException exception) { 
    throw new RuntimeException("Unexpected interrupt", exception); 
} 

Đó là nếu nó là bất ngờ. Có rất nhiều nơi mà tôi cố tình làm gián đoạn chủ đề của mình và trong những trường hợp đó, tôi xử lý các số InterruptedException theo cách được xác định rõ. Thông thường đó là bằng cách thoát khỏi bất kỳ vòng lặp nào tôi đang ở, dọn dẹp, và sau đó dừng thread.

1

Nếu bạn không biết làm thế nào để xử lý nó trong một phương pháp tôi đề nghị bạn khai báo nó trong phương pháp với ném InterruptedException (và nó gọi vv)

Nếu nó một cái gì đó bạn không bao giờ mong đợi để xảy ra tôi sẽ bắt nó và bọc nó trong AssertionError.

27

Có, bạn cần phải lo lắng về InterruptedException, cũng giống như bạn cần phải lo lắng về bất kỳ ngoại lệ đã kiểm tra nào khác mà bạn phải ném hoặc xử lý.

Hầu hết các lần InterruptedException báo hiệu yêu cầu dừng, rất có thể do thực tế là chuỗi đang chạy mã của bạn là interrupted.

Trong tình huống cụ thể của hồ bơi kết nối đang chờ kết nối, tôi cho rằng đây là vấn đề hủy và bạn cần hủy bỏ việc thu thập, dọn dẹp và khôi phục cờ bị gián đoạn (xem bên dưới).


Ví dụ, nếu bạn đang sử dụng một số loại Runnable/Callable chạy bên trong một Executor thì bạn cần phải xử lý các InterruptedException đúng:

executor.execute(new Runnable() { 

    public void run() { 
     while (true) { 
       try { 
       Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        continue; //blah 
       } 
       pingRemoteServer(); 
     } 
    } 
}); 

Điều này có nghĩa rằng nhiệm vụ của bạn không bao giờ tuân theo cơ chế gián đoạn được sử dụng bởi người thực thi và không cho phép hủy/tắt máy đúng cách.

Thay vào đó, các thành ngữ thích hợp là để khôi phục lại tình trạng gián đoạn và sau đó dừng thực hiện:

executor.execute(new Runnable() { 

    public void run() { 
     while (true) { 
       try { 
       Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        Thread.currentThread().interrupt(); // restore interrupted status 
        break; 
       } 
       pingRemoteServer(); 
     } 
    } 
}); 

nguồn lực hữu ích:

+3

Tuyệt đối. Để biết thêm thông tin, hãy xem bản tin Chuyên gia Java http://www.javaspecialists.co.za/archive/Issue056.html –

+1

Không nên là Thread.currentThread(). Interrupt() thay vì Thread.interrupted()? Theo javadocs, Thread.interrupted() sẽ xóa cờ bị gián đoạn, không đặt nó. –

+0

@Joe: bạn nói đúng, tôi đã sửa lại ví dụ. Cảm ơn bạn. –

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