2011-08-22 14 views
5

Cố gắng làm gián đoạn luồng đang chạy, trong ví dụ này, t1, được thực hiện bởi một luồng trong một nhóm luồng.Làm gián đoạn chủ đề đang ngủ

t2 là đoạn gửi ngắt.

Tôi không thể dừng chạy t1, t1 không nhận được InterruptedException.

Tôi đang thiếu gì?

Executor exec1 = Executors.newFixedThreadPool(1); 

    // task to be interrupted 
    Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      try { 
       System.out.println("starting uninterruptible task 1"); 
       Thread.sleep(4000); 
       System.out.println("stopping uninterruptible task 1"); 
      } catch (InterruptedException e) { 
       assertFalse("This line should never be reached.", true); 
       e.printStackTrace(); 
      }    
     }   
    }; 
    final Thread t1 = new Thread(runnable); 


    // task to send interrupt 
    Runnable runnable2 = new Runnable() { 
     @Override 
     public void run() { 
      try { 
       Thread.sleep(1000); 
       t1.interrupt(); 
       System.out.println("task 2 - Trying to stop task 1"); 
       Thread.sleep(5000); 

      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      }    
     }   
    }; 
    Thread t2 = new Thread(runnable2); 

    exec1.execute(t1); 
      t2.start(); 
    t2.join(); 

Trả lời

3

Dường như bạn hiểu sai chủ đề và Công tố viên. Bạn tạo hai chủ đề đối tượng cho hai runnables, nhưng chỉ bắt đầu một trong số chúng (t2), t1 bạn chuyển tới Executor để chạy bên trong nó. Nhưng thực thi không cần Thread để được cung cấp - nó chỉ cần thực hiện Runnable. Executor chính nó là một hồ bơi thread (thường, nhưng nó không cần thiết), và nó chỉ tạo ra (và hồ bơi) chủ đề bên trong nó. Nó thấy bạn chỉ đơn giản là Runnable (đó là Thread thực hiện). Vì vậy, bạn thực sự gửi gián đoạn đến chuỗi chưa bao giờ bắt đầu.

Nếu bạn thực sự muốn làm cho mã của bạn hoạt động, bạn nên loại bỏ Executor và chỉ bắt đầu cả hai luồng một cách rõ ràng.

+0

Cảm ơn BegemoT. Điều này thật ý nghĩa. – portoalet

+0

begemot đã làm đúng –

0

Để ngắt thread thi hành di chúc,

final ExecutorService exec1 = Executors.newFixedThreadPool(1); 
final Future<?> f = exec1.submit(runnable); 
... 
f.cancel(true); 
+0

Vấn đề với điều này là 'Runnable' bây giờ sẽ được thực hiện hai lần: một lần thông qua hồ bơi luồng và một lần thông qua chuỗi 't1'. –

+0

Tôi đang sử dụng trình thực thi để thực hiện chuỗi. – portoalet

+0

'cuối cùng Tương lai f = exec1.submit (runnable); f.cancel (true);' –

0

Calling Thread.interrupt không nhất thiết phải ném một InterruptedException. Nó chỉ có thể thiết lập trạng thái ngắt của luồng, có thể được hỏi bởi Thread.interrupted() hoặc Thread.isInterrupted.

Xem http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#interrupt() để biết thêm chi tiết.

+0

Bạn đã sai, đọc tài liệu cẩn thận .. phương pháp intterupt gây gián đoạn ngoại lệ, nếu thread bị gián đoạn đang ngủ .. –

+0

.. .if sợi bị gián đoạn đang ngủ ... Đó là ý của tôi, có thể sợi chỉ không ngủ khi nó bị gián đoạn. – mort

+0

nhưng chuỗi ở câu hỏi là trạng thái ngủ .. –

3

Lỗi của bạn là bạn đang cố gắng thực hiện một số Thread trên số ThreadPool.

này xuất hiện để làm việc, vì Thread xảy ra để thực hiện Runnable, nhưng vì sợi chỉ được sử dụng như một Runnable và không được bắt đầu như là một Thread, kêu gọi các phương pháp như #interrupt() sẽ không có hiệu quả mong muốn.

Nếu bạn vẫn cần sử dụng hồ bơi chuỗi, thay vào đó bạn nên xem xét sử dụng một lớp học như FutureTask. Hãy bọc Runnable của bạn trong một FutureTask và sau đó gửi tác vụ đó đến một nhóm luồng. Sau đó, khi bạn muốn làm gián đoạn tác vụ, hãy gọi futureTask.cancel(true).

1

Vấn đề là bạn không bao giờ thực sự biết được thread nào sẽ được sử dụng bởi Executor để chạy tác vụ của bạn.

Mặc dù bạn đã gửi một đối tượng Thread, Người thực thi sẽ sử dụng chuỗi được tạo bởi nhóm chủ đề cố định. Do đó, luồng có tham chiếu t1 không phải là luồng mà tác vụ của bạn sẽ được thực thi. để gọi t1.interrupt() sẽ không làm gì cả.

Để thực hiện đúng cách này, hãy sử dụng số ExecutorService và sử dụng submit() để gửi đối tượng Runnable/Callable. Điều này sẽ trả về một số Future, hiển thị phương thức cancel() có thể được sử dụng để hủy tác vụ.

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