Группировка потоков — интересная функция, предоставляемая API параллелизма Java. Мы можем рассматривать группу потоков как независимую единицу и манипулировать объектами потоков в группе потоков по своему желанию. Например, вы можете управлять группой потоков для выполнения одной и той же задачи, не заботясь о том, сколько потоков еще работает, а также вы можете использовать вызов прерывания, чтобы прервать выполнение всех потоков.
Java предоставляет класс ThreadGroup для управления группой потоков. Группа потоков может быть создана с помощью объекта потока или других групп потоков для создания древовидной структуры потоков.
Согласно «Эффективной Java», использование ThreadGroup больше не рекомендуется. Рекомендуется использовать Executor.
——Д Гуаго объясняет это.
В этом разделе мы используем ThreadGroup для разработки простого примера. Мы создадим десять потоков с разным временем сна (как имитируя поиск), и когда один из них завершится, прервем остальные.
знай это
Выполните шаги, показанные ниже, чтобы завершить пример кода.
1. Создайте класс с именем Result, чтобы сохранить имя первого потока, выполнившего задачу. Объявите частную переменную типа String, name и сгенерируйте методы Setter/Getter. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
результат публичного класса {
частное имя строки;
публичная строка getName() {
вернуть имя;
}
public void setName (имя строки) {
это.имя = имя;
}
}
2. Создайте класс с именем SearchTask и реализуйте интерфейс Runnable. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
публичный класс SearchTask реализует Runnable {
3. Объявите частную переменную типа Result и создайте экземпляр этой переменной через конструктор. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
частный результат результата;
public SearchTask (результат результата) {
this.result = результат;
}
4. Реализуйте метод run() и вызовите в нем метод doTask(), чтобы дождаться завершения или прерывания. Этот метод также выводит на консоль информацию, показывающую начало, конец или прерывание потока. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
@Override
общественный недействительный запуск () {
Имя строки = Thread.currentThread().getName();
System.out.printf("Поток %s: Start/n", name);
пытаться {
сделатьЗадачу();
result.setName(имя);
} catch (InterruptedException e) {
System.out.printf("Поток %s: Прерван/n", name);
возвращаться;
}
System.out.printf("Поток %s: End/n", name);
}
5. Реализуйте метод doTask(), который создаст объект Random, а затем будет использовать этот объект для генерации случайного числа для настройки времени сна потока. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
// Имитация поиска
Private void doTask() выдает InterruptedException {
Случайный случайный = новый случайный (новая дата().getTime());
значение int = (int) (random.nextDouble() * 100);
System.out.printf("Поток %s: %d/n",
Thread.currentThread().getName(), значение);
TimeUnit.SECONDS.sleep(значение);
}
6. Создайте основной класс примера программы Main и реализуйте метод main(). Код выглядит следующим образом:
Скопируйте код кода следующим образом:
общественный класс Main {
public static void main(String[] args) {
7. Создайте объект ThreadGroup с именем Searcher. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
ThreadGroup threadGroup = новая ThreadGroup («Искатель»);
8. Затем создайте объект Result и объект SearchTask. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
Результат Результат = новый Результат();
SearchTask searchTask = новый SearchTask (результат);
9. Используйте объект SearchTask для создания десяти объектов Thread, а при создании объекта Thread передайте объект ThreadGroup в качестве первого параметра конструктору класса Thread. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
для (int я = 0; я <5; я++) {
Поток потока = новый поток (threadGroup, searchTask);
поток.start();
пытаться {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
е.printStackTrace();
}
}
10. Используйте метод list() для распечатки информации об объекте ThreadGroup. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
System.out.printf("Количество потоков: %d/n", threadGroup.activeCount());
System.out.println("Информация о группе потоков");
группа потоков.список();
11. Используйте activeCount() и enumerate(), чтобы получить количество активных потоков в объекте ThreadGroup и скопировать его в массив потоков. Используйте метод get*(), чтобы получить имя и статус потока. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
Thread[] threads = новая тема[threadGroup.activeCount()];
threadGroup.enumerate(потоки);
for (int i = 0; i < threadGroup.activeCount(); i++) {
System.out.printf("Поток %s: %s/n", threads[i].getName(),
потоки[i].getState());
}
12. Вызовите метод waitFinish() и подождите, пока один из потоков в объекте ThreadGroup завершит задачу. Реализуйте этот метод позже. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
waitFinish (threadGroup);
13. Используйте метод прерывания(), чтобы прервать другие потоки в группе потоков. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
группа потоков.прерывание();
14. Реализуйте метод waitFinish() и используйте метод activeCount() для управления результатами выполнения потока. Код выглядит следующим образом:
Скопируйте код кода следующим образом:
// Ждем завершения задачи
Private static void waitFinish(ThreadGroup threadGroup) {
в то время как (threadGroup.activeCount() > 9) {
пытаться {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
е.printStackTrace();
}
}
}
15. Запустите программу и проверьте эффект выполнения.
знаю почему
Ниже приведен результат выполнения программы. Вы увидите выходные данные метода list(), статус каждого потока и т. д.
Скопируйте код кода следующим образом:
Поток Поток-0: Начало
Тема Тема-0: 52
Тема Тема-1: Начало
Тема Тема-1: 41
Тема Тема-2: Начало
Тема Тема-2: 69
Тема Тема-3: Начало
Нить Нить-3: 60
Тема Тема-4: Начало
Тема Тема-4: 88
Количество потоков: 5
Информация о группе потоков
java.lang.ThreadGroup[name=Searcher,maxpri=10]
Тема[Тема-0,5,Поиск]
Тема[Тема-1,5,Поиск]
Тема[Тема-2,5,Поиск]
Тема[Тема-3,5,Поиск]
Тема[Тема-4,5,Поиск]
Тема Тема-0: TIMED_WAITING
Тема Тема-1: TIMED_WAITING
Тема Тема-2: TIMED_WAITING
Тема Тема-3: TIMED_WAITING
Тема Тема-4: TIMED_WAITING
Поток Поток-1: Прервано
Поток-4: Прервано
Поток-2: Прервано
Поток Поток-0: Прерван
Поток Поток-3: Прервано
Класс ThreadGroup хранит множество объектов Thread и связанных с ними объектов ThreadGroup. Вы можете получить доступ к информации о потоке, вызвав методы этого класса, а также можете выполнять над ним различные операции, например прерывания.
бесконечный
Класс ThreadGroup также имеет множество методов. Пожалуйста, прочтите документацию по API для получения полного описания методов.
Используйте доктрину
Эта статья переведена из «Книги по параллелизму Java 7» (Д Гуа Ге украл ее как «Коллекция примеров параллелизма Java7») и используется только в качестве учебных материалов. Его нельзя использовать в коммерческих целях без разрешения.
Небольшой успех
Ниже приведена полная версия кода, используемого в примерах этого раздела.
Полный код класса Result:
Скопируйте код кода следующим образом:
пакет com.diguage.books.concurrencycookbook.chapter1.recipe10;
/**
* Хранить результаты запроса
* Дата: 30 сентября 2013 г.
* Время: 00:45
*/
результат публичного класса {
частное имя строки;
публичная строка getName() {
вернуть имя;
}
public void setName (имя строки) {
это.имя = имя;
}
}
Полный код класса SearchTask выглядит следующим образом:
пакет com.diguage.books.concurrencycookbook.chapter1.recipe10;
импортировать java.util.Date;
импортировать java.util.Random;
импортировать java.util.concurrent.TimeUnit;
/**
* Класс поиска моделирования
* Дата: 2 октября 2013 г.
* Время: 22:38
*/
публичный класс SearchTask реализует Runnable {
частный результат результата;
public SearchTask (результат результата) {
this.result = результат;
}
@Override
общественный недействительный запуск () {
Имя строки = Thread.currentThread().getName();
System.out.printf("Поток %s: Start/n", name);
пытаться {
сделатьЗадачу();
result.setName(имя);
} catch (InterruptedException e) {
System.out.printf("Поток %s: Прерван/n", name);
возвращаться;
}
System.out.printf("Поток %s: End/n", name);
}
// Имитация поиска
Private void doTask() выдает InterruptedException {
Случайный случайный = новый случайный (новая дата().getTime());
значение int = (int) (random.nextDouble() * 100);
System.out.printf("Поток %s: %d/n",
Thread.currentThread().getName(), значение);
TimeUnit.SECONDS.sleep(значение);
}
}
Полный код класса Main:
Скопируйте код кода следующим образом:
пакет com.diguage.books.concurrencycookbook.chapter1.recipe10;
импортировать java.util.concurrent.TimeUnit;
/**
* Пример основного класса группы потоков
* Дата: 2 октября 2013 г.
* Время: 22:45
*/
общественный класс Main {
public static void main(String[] args) {
ThreadGroup threadGroup = новая ThreadGroup («Искатель»);
Результат Результат = новый Результат();
SearchTask searchTask = новый SearchTask (результат);
для (int я = 0; я <5; я++) {
Поток потока = новый поток (threadGroup, searchTask);
поток.start();
пытаться {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
е.printStackTrace();
}
}
System.out.printf("Количество потоков: %d/n", threadGroup.activeCount());
System.out.println("Информация о группе потоков");
группа потоков.список();
Thread[] threads = новая тема[threadGroup.activeCount()];
threadGroup.enumerate(потоки);
for (int i = 0; i < threadGroup.activeCount(); i++) {
System.out.printf("Поток %s: %s/n", threads[i].getName(),
потоки[i].getState());
}
waitFinish (threadGroup);
группа потоков.прерывание();
}
// Ждем завершения задачи
Private static void waitFinish(ThreadGroup threadGroup) {
в то время как (threadGroup.activeCount() > 9) {
пытаться {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
е.printStackTrace();
}
}
}
}