2012-05-01 33 views
16

Gần đây tôi đã thừa kế một Ứng dụng Java lớn mà hầu như không có sự an toàn của Chủ đề trong đó. Những gì tôi hiện đang làm việc trên là nhận được tất cả các chủ đề để xử lý một cách chính xác bị gián đoạn thay vì sử dụng rất xấu Thread.stop().Phương thức xóa cờ Thread.interrupt()

Một phần của sự cố là tôi không biết mọi phương thức đều có thể xóa cờ ngắt.

Hiện nay tôi biết rằng sau đây sẽ xóa cờ ngắt:

Thread.interrupted() 
Thread.sleep(long) 
Thread.join() 
Thread.join(long) 
Object.wait() 
Object.wait(long) 

tôi thiếu gì nữa? Cảm ơn bạn

Trả lời

25

Một phần của sự cố là tôi không biết mọi phương thức đều có thể xóa cờ ngắt.

Điều quan trọng là phải làm rõ rằng các phương pháp sau đây rõ ràng cờ ngắt bằng cách chỉ gọi họ:

Thread.interrupted() 
Thread.isInterrupted(true) -- added to your list 

Vì lý do này Thread.currentThread().isInterrupted() nên luôn được sử dụng để thay thế.

Các phương pháp sau sẽ rõ ràng cờ bị gián đoạn bởi ngay ném InterruptedException hoặc nếu họ được kêu gọi và sau đó các chủ đề đã bị gián đoạn hoặc nếu thread được đã bị gián đoạn và sau đó họ được gọi là (xem mã junit dưới đây). Vì vậy, nó không phải là phương pháp xóa cờ, ném ngoại lệ.

Thread.sleep(long) 
Thread.join() 
Thread.join(long) 
Thread.join(int, long) – added to your list 
Object.wait() 
Object.wait(long) 
Object.wait(int, long) – added to your list 
BlockingQueue.put(...) – added to your list 
BlockingQueue.offer(...) – added to your list 
BlockingQueue.take(...) – added to your list 
BlockingQueue.poll(...) – added to your list 
Future.get(...) – added to your list 

Xin lưu ý rằng mô hình phù hợp với bất kỳ mã mà bắt InterruptedException là ngay lập tức tái ngắt thread. Chúng tôi làm điều này trong trường hợp người khác đang dựa vào thread.isInterrupted() phương pháp:

try { 
    ... 
} catch (InterruptedException e) { 
    // immediately re-interrupt the thread 
    Thread.currentThread().interrupt(); 
    // log the exception or [likely] quit the thread 
} 

đang JUnit đó chứng tỏ một số điều này:

assertFalse(Thread.currentThread().isInterrupted()); 
// you can do this from another thread by saying: someThread.interrupt(); 
Thread.currentThread().interrupt(); 
// this method does _not_ clear the interrupt flag 
assertTrue(Thread.currentThread().isInterrupted()); 
// but this one _does_ and should probably not be used 
assertTrue(Thread.interrupted()); 
assertFalse(Thread.currentThread().isInterrupted()); 
Thread.currentThread().interrupt(); 
assertTrue(Thread.currentThread().isInterrupted()); 
try { 
    // this throws immediately because the thread is _already_ interrupted 
    Thread.sleep(1); 
    fail("will never get here"); 
} catch (InterruptedException e) { 
    // and when the InterruptedException is throw, it clears the interrupt 
    assertFalse(Thread.currentThread().isInterrupted()); 
    // we should re-interrupt the thread so other code can use interrupt status 
    Thread.currentThread().interrupt(); 
} 
assertTrue(Thread.currentThread().isInterrupted()); 
10

Quy ước chung là như sau: bất kỳ phương pháp nào ném InterruptedException (+ Thread.interrupted()) sẽ xóa cờ ngắt.

Vì vậy, để làm cho chủ đề của bạn bị gián đoạn, bạn cần phải tìm tất cả các nơi mà InterruptedException bị bắt mà không cần khôi phục lại hoặc khôi phục cờ ngắt. Vì InterruptedException là ngoại lệ được kiểm tra, điều này không khó thực hiện.

+0

Đó là lần vượt qua đầu tiên đã ném trên cơ sở mã mà tôi đã thực hiện, tuy nhiên tôi đang đối mặt với một tình huống mà các lập trình viên trước đó sẽ bắt được một Ngoại lệ chung thay vì một InterruptedException. – OverflowingStack

1

Dưới đây là một ví dụ SUPER FUN:

ch.qos.logback .core.AsyncAppenderBase trước phiên bản 1.1.4 bắt và nuốt InterruptedException mà không cần đặt lại cờ trên chuỗi.

Vì vậy, nếu bạn sử dụng bất kỳ thứ gì định tuyến đến trình ghi nhật ký này (như slf4j), nó sẽ âm thầm ăn trạng thái ngắt luồng của bạn. 'Cos, ý tôi là, ai không kiểm tra trạng thái ngắt luồng trước và sau mỗi thao tác đăng nhập có thể?

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