2015-11-01 60 views
0

場景:我有一些獨立的任務將被賦予很少的線程來完成這些任務。主線程應等待所有線程完成其任務。雖然它在大多數時間都有效,但有時其中一個線程無法完成其任務,因此主線程無限期地等待。怎麼可能殺死被阻塞的線程?如何終止一個特定的阻塞線程

下面是解釋場景的示例代碼。

客戶端類

public class ThreadStop { 

public static void main(String[] args){ 

    List<Thread> threadList = getMyThreadList();   

    for (Thread thread : threadList) { 
     thread.start(); 
    } 

    System.out.println("Waiting for Child Threads to die"); 

    for (Thread thread : threadList) { 
     try { 
      thread.join(); 
      System.out.println(thread.getName() + " Finished its job");    
     } catch (InterruptedException e) { 
      System.out.println("Interrupted Exception thrown by : " 
        + thread.getName());     
     } 
    } 

    System.out.println("All Child Threads Finished their Job"); 
} 

private static List<Thread> getMyThreadList() { 
    List<Thread> threadList = new ArrayList<>(); 
    MyThread myThread; 
    Thread thread; 
    for(int i=0; i<10; i++){ 
     myThread = new MyThread(); 
     thread = new Thread(myThread); 
     thread.setName("Thread "+i); 
     threadList.add(thread); 
    } 
    return threadList; 
} 
} 

Thread類

public class MyThread implements Runnable{ 

@Override 
public void run() { 
    System.out.println("hello world by thread "+  Thread.currentThread().getName());   
} 

} 

注意請注意,我不能使用執行人框架。

+1

*我不能使用executor framework *:爲什麼?爲什麼這個任務從未完成?它是否被阻止等待輸入?它陷入了無限循環嗎?這很重要:如果它是一個錯誤,它應該被修復。如果阻止等待,那麼你應該能夠中斷它。告訴我們被阻止的任務在做什麼。 –

+0

@JBNizet我不能使用executor框架,因爲它的部分現有代碼庫不使用框架。如果我們必須使用它,將會有很多重構。被阻塞的任務會進行網絡通話,有時它似乎只是掛起。 –

+0

一種方法是使用volatile布爾值,該值指示線程是繼續運行還是應該停止。主線程可以適當地設置布爾值的值。另一個建議是中斷阻塞線程並在捕獲中斷異常時清理並退出邏輯。當然,如果線程代碼中存在無限循環或其他錯誤,這將不起作用。 – turingcomplete

回答

0

如果任務直接寫入子類Thread,那麼使用Executor框架[1]。在這種情況下,您應該使用帶有超時值的join()。如果加入不成功,您可以interrupt()該線程(但這不是一個保證'殺死')。直接撥動線不是一種很好的做事方式 - 它就像一個總是輸球的比賽,唯一的贏球就是不發揮。但是,如果任務寫得稍微更理性/受益於現代洞察力,它們將至少可以被封裝爲Runnable(或者確實,它們是Runnable並且僅傳遞給Thread的構造函數)。此時您可以再次使用Executor框架。

  1. 雖然你可以直接傳遞線程的情況下,以一個Executor,前提是你能避免調用start()run()的線程其他地方的代碼(因爲如果其他代碼也執行相同的任務,那麼,任務在最佳情況下執行兩次)。
+0

嗯。線程實現Runnable。您可以將線程傳遞給執行程序。不是設計代碼的最佳方式,但它是正確的。 –

+0

啊不錯,陷阱! – user268396

+0

@JBNizet添加了你的觀察,注意:如果其他代碼在線程上'手動'調用'start()'或'run()',它將無法正常工作,因爲(最好的情況)同一個任務被執行兩次。 – user268396