2012-09-01 31 views
6

Tôi đang phát triển một ứng dụng đa luồng để tạo các kết nối tới các máy chủ bên ngoài - mỗi trên các luồng riêng biệt - và sẽ bị chặn cho đến khi có đầu vào. Mỗi lớp mở rộng lớp Thread. Để giải thích, hãy gọi những "chuỗi kết nối" này.Java: Làm thế nào để bắt InterruptedException trên một sợi, khi bị gián đoạn bởi một luồng khác?

Tất cả các chuỗi kết nối này được lưu trữ trong một băm đồng thời.

Sau đó, tôi cho phép gọi phương thức dịch vụ web RESTful để hủy bất kỳ chủ đề nào. (Tôi đang sử dụng Grizzly/Jersey, vì vậy mỗi cuộc gọi là một chủ đề riêng của mình.)

Tôi truy xuất chuỗi kết nối cụ thể (từ hashmap) và gọi phương thức ngắt() trên đó.

Vì vậy, đây là câu hỏi, trong chuỗi kết nối, làm thế nào để tôi nắm bắt được InterruptedException? (Tôi muốn làm điều gì đó khi chuỗi kết nối bị dừng bởi một lệnh RESTful bên ngoài.)

+0

Vâng, AFAIK, khi một chuỗi ném InterruptedEx. nó sẽ lan truyền đến chủ đề đã bắt đầu chuỗi ném ngoại lệ. Đó là tại thread cha mà bạn có thể bắt IE. –

+0

Tôi vừa làm một thử nghiệm để bao quanh mã bắt đầu chuỗi kết nối và trình biên dịch cảnh báo rằng InterruptedException không bị ném. – ikevin8me

+0

Hơn nữa, chuỗi chủ đề bắt đầu các chuỗi kết nối đó không đi vào trạng thái chờ hoặc trạng thái ngủ, vì vậy nó có nghĩa là (hoặc ít nhất là tôi nghĩ) nó ngừng tồn tại sau khi nó đã bắt đầu tất cả các chuỗi con đó. – ikevin8me

Trả lời

6

Vì vậy, đây là câu hỏi, trong chuỗi kết nối, làm thế nào để tôi bắt được InterruptedException?

Bạn không thể. Vì nếu chuỗi của bạn bị chặn trên một hoạt động đọc/ghi, nó không thể là interrupted. Điều này là do interrupt chỉ đặt cờ để cho biết rằng chuỗi đã bị gián đoạn. Nhưng nếu chủ đề của bạn đã bị chặn cho I/O, nó sẽ không thấy cờ.
Cách thích hợp cho việc này là đóng ổ cắm bên dưới (thread bị chặn), sau đó bắt ngoại lệ và truyền nó lên.
Vì vậy, kể từ khi kết nối của bạn đề extend Thread làm như sau:

@Override 
public void interrupt(){ 
    try{ 
     socket.close(); 
    } 
    finally{ 
    super.interrupt(); 
    } 
} 

Bằng cách này nó có thể làm gián đoạn một sợi bị chặn trên I/O.

Sau đó, trong phương pháp run bạn làm:

@Override 
public void run(){ 

    while(!Thread.currentThread().isInterrupted()){  
     //Do your work 

    } 
}  

Vì vậy, trong trường hợp của bạn không nên cố gắng để catch một InterruptedException. Bạn không thể ngắt chuỗi bị chặn trên I/O. Chỉ cần kiểm tra xem chuỗi của bạn có bị gián đoạn hay không và tạo thuận lợi cho gián đoạn bằng cách đóng luồng.

2

vấn đề với chặn.

Hoverer, hãy thử mã này, có thể nó sẽ giúp bạn:

try{ 
yourObject.read(); 
}catch(InterruptedException ie){ 
// interrupted by other thread 
} 
catch(Exception ex){ 
// io or some other exception happent 
} 

phương pháp đọc của bạn, nên kiểm tra xem có buytes sẵn ở ổ cắm cho ví dụ, nếu có hơn đọc nó, othervise đi đến speel chế độ. Khi ngủ hơn là có sẵn các thức dậy (InterruptedException) tại ổ cắm đọc đọc (bất cứ điều gì đọc có bạn) nó sẽ bị chặn. Một số API có giá trị để chờ tối đa, ví dụ: 5 giây 60 giây, nếu không có gì o đọc hơn là mã tiếp theo sẽ được thực thi.

class MyReadingObject 
{ 
    public read() throws InterruptedException{ 
     while(shouldIread){ 
     if(socket.available() > 0){ 
      byte[] buff = new byte[socket.avaialble()] 
      socket.read(buff); 
      return; 
     } 
     else{ 
      Thread.currentThread.sleep(whateverMilliseconds); 
     } 
    } 
    } 
} 

một cái gì đó như thế, nhưng với xử lý lỗi và một số mẫu thiết kế

+0

Tôi đã thử một cái gì đó như thế này, vấn đề là "yourObject.read()" không ném InterruptedException. Trình biên dịch sẽ hiển thị một lỗi mà không có nơi nào trong mã ném ngoại lệ đó và từ chối biên dịch. – ikevin8me

+0

oh, nhưng bạn có thể thêm nó: –

+0

Tôi thấy tôi đã downvoted, tôi nên xem xét lại bao nhiêu thời gian tôi sẽ lãng phí ở đây. cảm ơn tất cả. Hãy giúp đỡ, chúc may mắn! –

-1

Sử dụng try-catch như vậy:

try { 
    //code 
} catch (InterruptedException e) { 
    //interrupted 
} 

Tôi nghĩ rằng nên làm như lừa, bạn cũng có thể giữ một biến boolean về việc có thoát hay không, vì vậy chúng sẽ kiểm tra biến đó, nếu đúng, hãy dừng

+0

Tôi nên đặt cái này ở đâu? Trong phương thức run()? - Trình biên dịch sẽ nói mã không ném InterruptedException và sẽ không biên dịch. – ikevin8me

2

Khi bạn gọi Thread.interrupt() trên một số chủ đề, điều gì xảy ra là 'interru cờ ption 'được đặt cho chuỗi đó. Một số phương pháp kiểm tra cờ này (bằng cách Thread.interrupted() hoặc Thread.isInterrupted()) và ném InterruptedException, nhưng thường chỉ có các phương pháp có thể chặn làm điều đó. Vì vậy, không có đảm bảo rằng InterruptedException sẽ bao giờ được ném vào chuỗi bị gián đoạn. Nếu bạn không gọi bất kỳ phương thức nào ném số InterruptedException, không có điểm nào trong việc bắt ngoại lệ đó, vì nó sẽ không được ném ra. Tuy nhiên, bạn luôn có thể kiểm tra xem chuỗi của mình có bị gián đoạn hay không bằng cách gọi Thread.isInterrupted().

+0

rất đúng, bạn cần gọi mycontroller.getReadingThread(). Interrupt(); –

1

Gọi interrupt() trên một sợi không dừng, nó chỉ chuyển sang cờ ngắt. Đó là trách nhiệm của mã để xử lý sự thay đổi trong trạng thái ngắt của luồng trong việc xem xét và hành động phù hợp. Nếu bạn đang thực hiện một hoạt động chặn trong chủ đề đó, bạn đang khá nhiều SOL vì thread của bạn là "chặn" trên đọc. Hãy xem câu trả lời mà tôi đã đăng here. Vì vậy, về cơ bản, trừ khi bạn đang looping qua nội dung hoặc định kỳ kiểm tra một số cờ bên trong chuỗi đó, bạn không có cách nào thoát ra mà không đóng các ổ cắm hoặc nội dung tương tự.

Một giải pháp ở đây là "hiển thị rõ ràng" đối tượng kết nối cơ bản và gọi close() trên đó, buộc phải loại bỏ một số ngoại lệ, sau đó có thể xử lý trong mã chuỗi. Một cái gì đó như:

class MyAction extends Thread implements Disposable { 

    public void doStuff() { 
    try { 
     byte[] data = this.connection.readFully(); 
    } catch (InterruptedException e) { 
    // possibly interrupted by forceful connection close  
    } 

    @Override 
    public void dispose() { 
    this.connection.close(); 
    } 
} 

// Elsewhere in code 
MyAction action = conMap.get("something"); 
action.dispose(); 
Các vấn đề liên quan