In the previous section "Thread Interruption", we explained how to interrupt an executing thread and what we must do to Thread in order to interrupt the thread. In general, we can use the interrupt mechanism introduced in the previous section. However, if the thread implements a complex algorithm that is distributed among multiple methods, or if there is a recursive call in the method call, we should use a better way to control the interruption of the thread. For this purpose, Java provides InterruptedException. This exception can be thrown when an interrupt request is detected and caught in the run() method.
In this section, we will use a thread to search for files in a specified directory and its subdirectories to demonstrate controlling thread interruption by using InterruptedException.
know it
Follow the steps shown below to implement the sample program.
1. Create a class named FileSearch and implement the Runnable interface. The code is as follows:
Copy the code code as follows:
public class FileSearch implements Runnable {
2. Declare two variables, one for the file name to be searched, and one for initializing the directory to be searched; implement the constructor of the class, and initialize the two variables just declared with the parameters of the constructor. The code is as follows:
Copy the code code as follows:
private String initPath;
private String fileName;
public FileSearch(String initPath, String fileName) {
this.initPath = initPath;
this.fileName = fileName;
}
3. Implement the run() method, which checks whether fileName is a path name. If so, call the directoryProcess() method for processing. The directoryProcess() method throws InterruptedException, so we need to catch the exception. The code is as follows:
Copy the code code as follows:
@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());
}
}
}
In the original article, the method name mentioned is processDirectory(). However, according to the procedure below, it is a clerical error. So correct it.
4. Implement the directoryProcess() method. This method reads all files and subdirectories in the specified directory and then processes them. For each directory, this method makes a recursive call to process the directory specified by the parameter. For each file, this method calls the fileProcess() method. After processing all directories and files, this method will check whether the thread is interrupted, which is to throw an InterruptedException exception. The code is as follows:
Copy the code code as follows:
/**
* Process a directory
*
* @param file directory to be processed
* @throws InterruptedException
*/
private void directoryProcess(File file) throws InterruptedException {
File[] list = file.listFiles();
if (null != list) {
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. Implement the fileProcess() method, which compares the file being processed with the file name to be found. If the file names are equal, a message is printed to the console. The thread then checks to see if it was interrupted, and if so, throws an InterruptedException. The code is as follows:
Copy the code code as follows:
/**
* Processed files
*
* @param file file to be processed
* @throws InterruptedException
*/
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. Now, implement the main class of the example and implement the main() method. The code is as follows:
Copy the code code as follows:
public class Main {
public static void main(String[] args) {
7. Create and initialize the FileSearch object, and then create a Thread object to perform the task. Then, start the thread. The code is as follows:
Copy the code code as follows:
FileSearch fileSearch = new FileSearch("C://", "autoexec.bat");
Thread thread = new Thread(fileSearch);
thread.start();
8. Wait ten seconds and then interrupt the thread. The code is as follows:
Copy the code code as follows:
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
9. Execute the example and view the results.
know why
The following is the result of thread execution. It can be seen from the output how the thread execution is terminated when FileSearch detects that it has been interrupted.
Copy the code code as follows:
Thread-0: C:/autoexec.bat
Thread-0: The search has been interrupted
In this example, we use Java exceptions to control thread interruption. When you run the example, the program checks whether the specified directory and its subdirectories contain the target file. For example, if you enter /b/c/d, the program will recursively call the directoryProcess() method three times. When the thread detects that it has been interrupted, an InterruptedException will be thrown. No matter how many recursive calls are performed, the program will start executing the run() method.
never ending
InterruptedException exceptions are generally thrown by Java concurrency APIs, such as the sleep() method.
Use doctrine
This article is translated from "Java 7 Concurrency Cookbook" (D Gua Ge stole it as "Java7 Concurrency Example Collection") and is only used as learning materials. It may not be used for any commercial purposes without authorization.
Small success
The complete code of the FileSearch class is as follows:
package com.diguage.books.concurrencycookbook.chapter1.recipe4;
import java.io.File;
/**
* Date: 2013-09-18
* Time: 18:21
*/
public class FileSearch implements Runnable {
private String initPath;
private String fileName;
/**
* Initialization constructor
*
* @param initPath The directory to be searched
* @param fileName The name of the file to be found
*/
public FileSearch(String initPath, String fileName) {
this.initPath = initPath;
this.fileName = fileName;
}
@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());
}
}
}
/**
* Process a directory
*
* @param file directory to be processed
* @throws InterruptedException
*/
private void directoryProcess(File file) throws InterruptedException {
File[] list = file.listFiles();
if (null != list) {
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();
}
}
/**
* Processed files
*
* @param file file to be processed
* @throws InterruptedException
*/
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();
}
}
}
The complete code of Main class
Copy the code code as follows:
package com.diguage.books.concurrencycookbook.chapter1.recipe4;
import java.util.concurrent.TimeUnit;
/**
* Date: 2013-09-18
* Time: 19:28
*/
public class Main {
public static void main(String[] args) {
FileSearch fileSearch = new FileSearch("C://", "autoexec.bat");
Thread thread = new Thread(fileSearch);
thread.start();
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}