Управление группами процессов
Возвращаясь к обсуждению темы безопасности можно сказать, что одна вещь похоже будет полезной для управления процессами: можно выполнить определенную операцию над всей группой процессов с помощью одной команды. Следующий пример демонстрирует это, а также ограничение приоритетов внутри групп процессов. Закомментированный цифры в круглых скобках обеспечивают ссылку для сравнения результата работы.
//: c14:ThreadGroup1.java
// How thread groups control priorities
// of the threads inside them.
public class ThreadGroup1 { public static void main(String[] args) { // Get the system thread & print its Info:
ThreadGroup sys = Thread.currentThread().getThreadGroup(); sys.list(); // (1)
// Reduce the system thread group priority:
sys.setMaxPriority(Thread.MAX_PRIORITY - 1); // Increase the main thread priority:
Thread curr = Thread.currentThread(); curr.setPriority(curr.getPriority() + 1); sys.list(); // (2)
// Attempt to set a new group to the max:
ThreadGroup g1 = new ThreadGroup("g1"); g1.setMaxPriority(Thread.MAX_PRIORITY); // Attempt to set a new thread to the max:
Thread t = new Thread(g1, "A"); t.setPriority(Thread.MAX_PRIORITY); g1.list(); // (3)
// Reduce g1's max priority, then attempt
// to increase it:
g1.setMaxPriority(Thread.MAX_PRIORITY - 2); g1.setMaxPriority(Thread.MAX_PRIORITY); g1.list(); // (4)
// Attempt to set a new thread to the max:
t = new Thread(g1, "B"); t.setPriority(Thread.MAX_PRIORITY); g1.list(); // (5)
// Lower the max priority below the default
// thread priority:
g1.setMaxPriority(Thread.MIN_PRIORITY + 2); // Look at a new thread's priority before
// and after changing it:
t = new Thread(g1, "C"); g1.list(); // (6)
t.setPriority(t.getPriority() -1); g1.list(); // (7)
// Make g2 a child Threadgroup of g1 and
// try to increase its priority:
ThreadGroup g2 = new ThreadGroup(g1, "g2"); g2.list(); // (8)
g2.setMaxPriority(Thread.MAX_PRIORITY); g2.list(); // (9)
// Add a bunch of new threads to g2:
for (int i = 0; i < 5; i++) new Thread(g2, Integer.toString(i)); // Show information about all threadgroups
// and threads:
sys.list(); // (10)
System.out.println("Starting all threads:"); Thread[] all = new Thread[sys.activeCount()]; sys.enumerate(all); for(int i = 0; i < all.length; i++) if(!all[i].isAlive()) all[i].start(); // Suspends & Stops all threads in
// this group and its subgroups:
System.out.println("All threads started"); sys.suspend(); // Deprecated in Java 2
// Never gets here...
System.out.println("All threads suspended"); sys.stop(); // Deprecated in Java 2
System.out.println("All threads stopped"); } } ///:~
Результат работы программы, представленный ниже, был отредактирован, чтобы уместиться на странице (java.lang. удалено), а также добавлены цифры, чтобы ссылаться на закомментированные цифры по тексту программы приведенной выше.
(1) ThreadGroup[name=system,maxpri=10] Thread[main,5,system] (2) ThreadGroup[name=system,maxpri=9] Thread[main,6,system] (3) ThreadGroup[name=g1,maxpri=9] Thread[A,9,g1] (4) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1] (5) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1] Thread[B,8,g1] (6) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,6,g1] (7) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1] (8) ThreadGroup[name=g2,maxpri=3] (9) ThreadGroup[name=g2,maxpri=3] (10)ThreadGroup[name=system,maxpri=9] Thread[main,6,system] ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1] ThreadGroup[name=g2,maxpri=3] Thread[0,6,g2] Thread[1,6,g2] Thread[2,6,g2] Thread[3,6,g2] Thread[4,6,g2] Starting all threads: All threads started
У всех программ есть как минимум один запущенный процесс и первое действие в main() является вызовом static метода для Thread называемого currentThread(). Из этого процесса создается группа процессов и вызывается list() для отображения следующего результата:
(1) ThreadGroup[name=system,maxpri=10] Thread[main,5,system]
Можно видеть, что имя основной группы system, а имя основного процесса main и он принадлежит группе процессов system.
Второй пример (exercise) показывает, что максимальный приоритет группы system может быть уменьшен, а процесс main может увеличить свой приоритет:
(2) ThreadGroup[name=system,maxpri=9] Thread[main,6,system]
Третий пример создает группу процессов g1, которая автоматически принадлежит системной группе процессов поскольку для нее не установлено что-то иное. Новый процесс А помещается в g1. После попытки установить наивысшее значение для максимального приоритета этой группы и наивысшее значение для приоритет процесса А результат будет следующий:
(3) ThreadGroup[name=g1,maxpri=9] Thread[A,9,g1]
Таким образом, не возможно установить более высокое максимальное значение приоритета группы чем у ее предка.
Четвертый пример уменьшает максимальное значение приоритета для g1, а затем пытается вернуть его обратно к Thread.MAX_PRIORITY. Результат следующий:
(4) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1]
Можно видеть, что обратное увеличение до максимального приоритета не работает. Можно только уменьшить максимальное значение приоритета группы, но не увеличить его. Также обратите внимание, что приоритет процесса A не изменился и стал больше чем значение максимального приоритета для группы.
В пятом пример делается попытка установить у нового процесса максимальное значение приоритета:
(5) ThreadGroup[name=g1,maxpri=8] Thread[A,9,g1] Thread[B,8,g1]
Приоритет нового процесса не может быть изменен на большее, чем макимальное значение приорита группы.
Приоритет процесса по умолчанию для данной программы равен шести; это приоритет с которым будет создан новый процесс и с которым он останется, если не пытаться как-то его изменить. В примере 6 будем уменьшать максимальный приоритет группы до меньшего значения, чем приоритет процесса по умолчанию, чтобы увидеть, что произойдет в этих условиях:
(6) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,6,g1]
Хотя максимальный приоритет для группы и равен трем, новый процесс все равно создается с приоритетом по умолчанию, то есть шесть. Таким образом, максимальное значение приоритета группы процессов не влияет на приоритет по умолчанию. (Фактически не существует способа установить другое значение проритета по умолчанию для новых процессов.)
После изменения приоритета, попытка уменьшить его на единицу приводит к следующему:
(7) ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1]
Только когда вы пытаетесь изменить значение приоритета принудительно изменяется максимальное значение приоритета группы процессов.
Аналогичный эксперимент проводился в (8) и (9), в котором создается новая дочерняя группа процессов g2 от g1, а затем максимальное значение ее приоритета изменяется. И видно, что невозможно установить максимальное значение приоритета для g2 выше, чем у g1:
(8) ThreadGroup[name=g2,maxpri=3] (9) ThreadGroup[name=g2,maxpri=3]
Также видно, что в момент создания, g2 автоматически устанавливает приоритет в значение, равное максимальному приоритету группы g1.
После всех этих экспериментов выводиться полный список всех групп и процессов:
(10)ThreadGroup[name=system,maxpri=9] Thread[main,6,system] ThreadGroup[name=g1,maxpri=3] Thread[A,9,g1] Thread[B,8,g1] Thread[C,3,g1] ThreadGroup[name=g2,maxpri=3] Thread[0,6,g2] Thread[1,6,g2] Thread[2,6,g2] Thread[3,6,g2] Thread[4,6,g2]
Таким образом, согласно правилу для групп процессов, дочерняя группа всегда будет иметь приоритет, который меньше или равен максимальному значению приоритета группы предка.
Последняя часть данной программы демонстрирует методы для всей группы процессов. В начале программа перемещается по всему дереву процессов и запускает те из них, который еще не запущены. Чтобы все было не безоблачно, системная группа затем временно отключается (suspend) и, в конце концов, останавливается. (Также довольно интересно наблюдать как suspend() и work() работают со всей группой процессов, но помните, что данные методы запрещены (depricated) в Java 2.) Но в тот момент когда вы приостановили группу system, вы также приостанавливаете процесс main и вся программа падает (shut down), и она ни когда не дойдет до той точки, где программа останавливается. В действительности, при попытке остановить процесс main он генерирует исключение ThreadDeath, то есть не типичная ситуация. Поскольку ThreadGroup является наследником Object содержащий метод wait(), то можно также приостановить выполнение программы на какой-то промежуток времени вызовом wait(seconds * 1000). Конечно это должно установить блокировку внутри синхронизированного блока.
Класс ThreadGroup имеет также методы suspend( ) и resume( ), так что можно остановить и запустить всю группу процессов и все процессы и подгруппы в этой группе с помощью простых команд. (И еще раз, suspend( ) и resume( ) запрещены в Java 2.)
Группы процессов могут выглядеть мистическими на первый взгляд, но просто помните, что вам не придется слишком часто пользоваться ими непосредственно.