1. 程式人生 > >控制執行緒中斷

控制執行緒中斷

控制執行緒中斷


在上節中,我們學到如何中斷執行緒的執行,以及如何線上程物件中控制中斷。上節中用來展示執行緒可否被中斷的範例原理比較簡單。如果執行緒執行一個分成很多方法的複雜演算法或者包含遞迴呼叫的方法,就需要更好的機制來控制執行緒中斷。針對於此,Java提供IterruptedException異常,當探測到執行緒中斷時丟擲這個異常,並在run()方法中捕獲它。

在本節中,實現一個任務,查詢指定目錄以及其所有子目錄下確定名稱的檔案。用來展示如何使用IterruptedException異常來控制執行緒中斷。

準備工作

本範例通過Eclipse開發工具實現。如果使用諸如NetBeans的開發工具,開啟並建立一個新的Java專案。

實現過程

通過如下步驟完成範例:

  1. 建立FileSearch類,指定其實現Runnable介面:

    public class FileSearch implements Runnable {
    
  2. 定義兩個私有屬性:分別是將要尋找的檔名稱和初始目錄路徑。實現此類的建構函式,初始化兩個屬性:

    	private String initPath;
    	private String fileName;
    	public FileSearch(String initPath,
    String fileName){ this.initPath = initPath; this.fileName = fileName; }
  3. 實現FileSearch類的run()方法。判斷fileName屬性是否為目錄,如果是,呼叫directoryProcess()方法,這個方法能夠丟擲IterruptedException異常,所以能夠捕獲到:

        @Override
            public void run() {
                File file = new File(initPath);
                if(file.isDirectory
    ()){ try { directoryProcess(file); } catch (InterruptedException e) { System.out.printf("%s: The search has been interrupted", Thread.currentThread().getName()); } } }
  4. 實現directoryProcess()方法。此方法將獲得指定目錄下的檔案和子目錄並進行處理。對每個目錄,方法進行遞迴呼叫,遍歷目錄為引數。對每個檔案,將呼叫fileProcess()方法。處理完所有檔案和目錄後,此方法判斷執行緒是否已被中斷,如果是的情況,會丟擲一個IterruptedException異常:

        private void directoryProcess(File file) throws InterruptedException{
                File list[] = file.listFiles();
                if(list != null) {
                    for (int i = 0; i < list.length; i++){
                        if(list[i].isDirectory()) {
                            directoryProcess(list[i]);
                        }else{
                            fileProcess(list[i]);
                        }
                    }
                }
                if(Thread.interrupted()){
                    throw new InterruptedException();
                }
         }
    
  5. 實現fileProcess()方法。此方法將比較正在處理的檔案和需要尋找的檔案,如果名稱相同,控制檯會輸出一條資訊。比較過後,執行緒將判斷它是否已被中斷,如果是的情況,會丟擲一個IterruptedException異常:

        private void fileProcess(File file) throws InterruptedException{
                if(file.getName().equals(fileName)) {
                    System.out.printf("%s : %s\n", Thread.currentThread().getName(), file.getAbsolutePath());
                }
                if(Thread.interrupted()){
                    throw new InterruptedException();
                }
    	}
    
  6. 現在實現主類。建立一個包含main()方法的Main類:

    public class Main {
    	public static void main(String[] args) {
    
  7. 建立和初始化FileSearch類的物件和執行任務的執行緒,然後開始執行執行緒。這裡使用的是Windows作業系統路徑。如果用其他作業系統例如Linux或者iOS開發,更改相應路徑:

    		FileSearch searcher = new FileSearch("C:\\Windows", "explorer.exe");
    		Thread thread = new Thread(searcher);
    		thread.start();
    
  8. 等待10秒鐘,中斷執行緒:

    		try {
    			TimeUnit.SECONDS.sleep(10);
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    		thread.interrupt();
    	}
    
  9. 執行程式,檢視結果。

工作原理

下圖展現範例的執行結果。可以看到FileSearch物件結束執行緒執行,以及當執行緒檢測到已被中斷時停止執行。

pics/01_04.jpg

在範例中,我們使用Java異常來控制執行緒的中斷。當執行範例時,程式遍歷資料夾來判斷是否存在對應檔案。例如,如果進入\b\c\d資料夾,程式將遞迴三次呼叫directoryProcess()方法。當檢測到執行緒已被中斷,無論遞迴呼叫多少次,run()方法都會丟擲IterruptedException異常,並且繼續執行。

擴充套件學習

IterruptedException異常是由與併發API相關的Java方法丟擲的,例如sleep()。如果執行緒在休眠的時候被中斷(用interrupt()方法),就會丟擲這個異常。

更多關注

本章中“中斷執行緒”小節。