В предыдущем разделе «Прерывание потока» мы объяснили, как прервать выполняющийся поток и что мы должны сделать с потоком, чтобы прервать поток. В общем, мы можем использовать механизм прерываний, представленный в предыдущем разделе. Однако, если поток реализует сложный алгоритм, распределенный между несколькими методами, или если в вызове метода есть рекурсивный вызов, нам следует использовать лучший способ управления прерыванием потока. Для этой цели Java предоставляет InterruptedException. Это исключение может быть выброшено, когда запрос на прерывание обнаружен и перехвачен методом run().
В этом разделе мы будем использовать поток для поиска файлов в указанном каталоге и его подкаталогах, чтобы продемонстрировать управление прерыванием потока с помощью InterruptedException.
знай это
Выполните шаги, показанные ниже, чтобы реализовать пример программы.
1. Создайте класс с именем FileSearch и реализуйте интерфейс Runnable. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
публичный класс FileSearch реализует Runnable {
2. Объявите две переменные: одну для имени файла, в котором необходимо выполнить поиск, и одну для инициализации каталога, в котором будет выполняться поиск; реализуйте конструктор класса и инициализируйте две только что объявленные переменные с параметрами конструктора. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
частная строка initPath;
частная строка имя_файла;
public FileSearch (String initPath, String fileName) {
this.initPath = initPath;
это.ИмяФайла = ИмяФайла;
}
3. Реализуйте метод run(), который проверяет, является ли имя_файла именем пути. Если да, вызовите метод DirectoryProcess() для обработки. Метод DirectoryProcess() генерирует InterruptedException, поэтому нам нужно перехватить это исключение. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
@Override
общественный недействительный запуск () {
Файл файл = новый файл (initPath);
если (file.isDirectory()) {
пытаться {
КаталогПроцесс (файл);
} catch (InterruptedException e) {
System.out.printf("%s: поиск прерван",
Thread.currentThread().getName());
}
}
}
В исходной статье упоминается имя методаprocessDirectory(). Однако, согласно приведенной ниже процедуре, это техническая ошибка. Так что поправьте.
4. Реализуйте метод DirectoryProcess(). Этот метод считывает все файлы и подкаталоги в указанном каталоге, а затем обрабатывает их. Для каждого каталога этот метод выполняет рекурсивный вызов для обработки каталога, указанного параметром. Для каждого файла этот метод вызывает метод fileProcess(). После обработки всех каталогов и файлов этот метод проверит, прерван ли поток, то есть выдаст исключение InterruptedException. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
/**
* Обработка каталога
*
* @param каталог файлов для обработки
* @throws InterruptedException
*/
частный недействительный каталогПроцесс (Файл-файл) выдает InterruptedException {
Список файлов[] = file.listFiles();
если (ноль != список) {
for (int i = 0; i <list.length; i++) {
если (список[i].isDirectory()) {
DirectoryProcess (список [я]);
} еще {
fileProcess (список [я]);
}
}
}
если (Thread.interrupted()) {
выбросить новое InterruptedException();
}
}
5. Реализуйте метод fileProcess(), который сравнивает обрабатываемый файл с именем файла, который необходимо найти. Если имена файлов совпадают, на консоль выводится сообщение. Затем поток проверяет, был ли он прерван, и если да, то выдает InterruptedException. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
/**
* Обработанные файлы
*
* @param file файл для обработки
* @throws InterruptedException
*/
Private void fileProcess (Файл-файл) выдает InterruptedException {
если (file.getName().equals(fileName)) {
System.out.printf("%s: %s/n",
Thread.currentThread().getName(),
file.getAbsolutePath());
}
если (Thread.interrupted()) {
выбросить новое InterruptedException();
}
}
6. Теперь реализуйте основной класс примера и метод main(). Код выглядит следующим образом:
Скопируйте код кода следующим образом:
общественный класс Main {
public static void main(String[] args) {
7. Создайте и инициализируйте объект FileSearch, а затем создайте объект Thread для выполнения этой задачи. Затем запустите ветку. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
FileSearch fileSearch = новый FileSearch("C://", "autoexec.bat");
Поток потока = новый поток (fileSearch);
поток.start();
8. Подождите десять секунд, а затем прервите поток. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
пытаться {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
е.printStackTrace();
}
поток.прерывание();
9. Выполните пример и просмотрите результаты.
знаю почему
Ниже приведен результат выполнения потока. Из выходных данных видно, как выполнение потока прекращается, когда FileSearch обнаруживает, что оно было прервано.
Скопируйте код кода следующим образом:
Поток-0: C:/autoexec.bat
Тема-0: Поиск прерван
В этом примере мы используем исключения Java для управления прерыванием потока. При запуске примера программа проверяет, содержит ли указанный каталог и его подкаталоги целевой файл. Например, если вы введете /b/c/d, программа трижды рекурсивно вызовет метод DirectoryProcess(). Когда поток обнаруживает, что он был прерван, будет выброшено InterruptedException. Независимо от того, сколько рекурсивных вызовов будет выполнено, программа начнет выполнение метода run().
бесконечный
Исключения InterruptedException обычно генерируются API-интерфейсами параллелизма Java, такими как метод Sleep().
Используйте доктрину
Эта статья переведена из «Книги по параллелизму Java 7» (Д Гуа Ге украл ее как «Коллекция примеров параллелизма Java7») и используется только в качестве учебных материалов. Его нельзя использовать в коммерческих целях без разрешения.
Небольшой успех
Полный код класса FileSearch выглядит следующим образом:
пакет com.diguage.books.concurrencycookbook.chapter1.recipe4;
импортировать java.io.File;
/**
* Дата: 18 сентября 2013 г.
* Время: 18:21
*/
публичный класс FileSearch реализует Runnable {
частная строка initPath;
частная строка имя_файла;
/**
* Конструктор инициализации
*
* @param initPath Каталог, в котором выполняется поиск.
* @param fileName Имя искомого файла.
*/
public FileSearch (String initPath, String fileName) {
this.initPath = initPath;
это.ИмяФайла = ИмяФайла;
}
@Override
общественный недействительный запуск () {
Файл файл = новый файл (initPath);
если (file.isDirectory()) {
пытаться {
КаталогПроцесс (файл);
} catch (InterruptedException e) {
System.out.printf("%s: поиск прерван",
Thread.currentThread().getName());
}
}
}
/**
* Обработка каталога
*
* @param каталог файлов для обработки
* @throws InterruptedException
*/
Private void DirectoryProcess (Файл-файл) выдает InterruptedException {
Список файлов[] = file.listFiles();
если (ноль != список) {
for (int i = 0; i <list.length; i++) {
если (список[i].isDirectory()) {
DirectoryProcess (список [я]);
} еще {
fileProcess (список [я]);
}
}
}
если (Thread.interrupted()) {
выбросить новое InterruptedException();
}
}
/**
* Обработанные файлы
*
* @param file файл для обработки
* @throws InterruptedException
*/
Private void fileProcess (Файл-файл) выдает InterruptedException {
если (file.getName().equals(fileName)) {
System.out.printf("%s: %s/n",
Thread.currentThread().getName(),
file.getAbsolutePath());
}
если (Thread.interrupted()) {
выбросить новое InterruptedException();
}
}
}
Полный код основного класса
Скопируйте код кода следующим образом:
пакет com.diguage.books.concurrencycookbook.chapter1.recipe4;
импортировать java.util.concurrent.TimeUnit;
/**
* Дата: 18 сентября 2013 г.
* Время: 19:28
*/
общественный класс Main {
public static void main(String[] args) {
FileSearch fileSearch = новый FileSearch("C://", "autoexec.bat");
Поток потока = новый поток (fileSearch);
поток.start();
пытаться {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
е.printStackTrace();
}
поток.прерывание();
}
}