2011-08-22 149 views
5

試圖中斷正在運行的線程(在本例中爲t1),該線程由線程池中的線程執行。中斷睡眠線程

t2是發送中斷的那個。

我無法停止運行t1,t1沒有得到InterruptedException。

我錯過了什麼?

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(); 

回答

3

看起來像你誤解線程和執行者。您爲兩個runnable創建兩個線程對象,但只啓動其中的一個(t2),將t1傳遞給Executor以在其中運行。但是執行器不需要提供線程 - 它只需要Runnable實現。執行程序本身就是一個線程池(通常,但不是必需的),它只是在它內部創建(並池)線程。它看起來像線程一樣簡單Runnable(這是線程實現)。所以你真的發送中斷到從未開始的線程。

如果你真的想讓你的代碼有效,你應該刪除Executor,並且明確地啓動兩個線程。

+0

感謝BegemoT。這是有道理的。 – portoalet

+0

begemot已經對了 –

0

要中斷執行線程,

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

問題在於'Runnable'現在將執行兩次:一次通過線程池,一次通過線程't1'。 –

+0

我正在使用執行程序來執行線程。 – portoalet

+0

'最後的未來 f = exec1.submit(runnable); f.cancel(true);' –

0

調用了Thread.interrupt不一定拋出一個InterruptedException。它可能只是設置線程的中斷狀態,可以通過Thread.interrupted()或Thread.isInterrupted進行輪詢。

查看http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Thread.html#interrupt()瞭解更多詳情。

+0

你錯了,仔細閱讀文檔.. intterupt方法導致中斷的異常,如果中斷的線程正在睡眠.. –

+0

..如果被中斷的線程正在睡眠...... 這就是我的意思,也許線程在被中斷時不會休眠。 – mort

+0

但問題的線程處於睡眠狀態。 –

3

你的錯誤是,你試圖在ThreadPool上執行Thread

出現工作,因爲Thread恰好實現Runnable,但因爲線程只被用作Runnable,並沒有開始一個Thread,呼籲像#interrupt()方法將不會收到預期的效果。

如果您仍然需要使用線程池,則應該考慮使用類似FutureTask的類。將Runnable包裝在FutureTask中,然後將任務提交到線程池。然後,當您想要中斷任務時,請致電futureTask.cancel(true)

1

問題是,您永遠無法知道Executor將使用哪個線程來運行您的任務。

即使您提交了Thread對象,執行程序也將使用由固定線程池創建的線程。因此,引用t1的線程不是您的任務將要執行的線程。因此撥打t1.interrupt()不會做任何事情。

要正確執行此操作,請使用ExecutorService並使用submit()來提交Runnable/Callable對象。這將返回一個Future,該公開cancel()方法可用於取消任務。