Чтение онлайн

ЖАНРЫ

Основы программирования на Java

Сухов С. А.

Шрифт:
10.2. Подпроцесс

Класс Thread инкапсулирует все средства, которые могут вам потребоваться при работе с подпроцессами. При запуске Java-программы в ней уже есть один выполняющийся подпроцесс. Вы всегда можете выяснить, какой именно подпроцесс выполняется в данный момент, с помощью вызова статического метода Thread.currentThread. После того, как вы получите ссылку подпроцесса, вы можете выполнять над этим подпроцессом различные операции даже в том случае, когда параллельные подпроцессы отсутствуют. В очередном нашем примере показано, как можно управлять выполняющимся в данный момент подпроцессом.

class CurrentThreadDemo {

public static void main(String args[]) {

Thread t = Thread.currentThread;

t.setName("Moй
подпроцесс");

System.out. println("текущий подпроцесс: " +1);

try {

for (int n = 5; n > 0; n--) {

System.out.println(" " + n);

Thread.sleep(1000);

}

}

catch (InterruptedException e) {

System.out.println("interrupted");

}

}

В этом примере текущий подпроцесс хранится в локальной переменной t. Затем мы используем эту переменную для вызова метода setName, который изменяет внутреннее имя подпроцесса на «My Thread» с тем, чтобы вывод программы был удобочитаемым. На следующем шаге мы входим в цикл, в котором ведется обратный отсчет от 5, причем на каждой итерации с помощью вызова метода Thread.sleep делается пауза длительностью в 1 секунду. Аргументом для этого метода является значение временного интервала в миллисекундах. Обратите внимание — цикл заключен в try/catch блок. Дело в том, что метод Thread.sleep может возбуждать исключение InterruptedException. Это исключение возбуждается в том случае, если какому-либо другому подпроцессу понадобится прервать данный подпроцесс. В данном примере мы в такой ситуации просто выводим сообщение о перехвате исключения. Ниже приведен вывод этой программы:

С:\> java CurrentThreadDemo

текущий подпроцесс: Thread[Moй подпроцесс,5,main]

5

4

3

2

1

Обратите внимание на то, что в текстовом представлении объекта Thread содержится заданное нами имя легковесного процесса — Мой подпроцесс. Число 5 — это приоритет подпроцесса, оно соответствует приоритету по умолчанию, «main» — имя группы подпроцессов, к которой принадлежит данный подпроцесс.

10.3. Интерфейс Runnable

Как можно создать еще один подпроцесс? Для этого нам понадобится другой экземпляр класса Thread. При создании нового объекта Thread ему нужно указать, какой программный код он должен выполнять. Вы можете запустить подпроцесс с помощью любого объекта, реализующего интерфейс Runnable. Для того чтобы реализовать этот интерфейс, класс должен предоставить определение метода run. Ниже приведен пример, в котором создается новый подпроцесс.

class ThreadDemo implements Runnable {

ThreadDemo {

Thread ct = Thread.currentThread;

System.out.println("currentThread: " + ct);

Thread t = new Thread(this, "Demo Thread");

System.out.println("Thread created: " +1);

t.start;

try {

Thread.sleep(3000);

}

catch (InterruptedException e) {

System.out.println("прерывание");

}

System.out.println("Выход из main подпроцесса");

}

public void run {

try {

for (int i = 5; i > 0; i--) {

System.out.println("" + i);

Thread.sleep(l000);

}

}

catch (InterruptedException e) {

System.out.println("child
прерван");

}

System.out.println("Выход из child подпроцесса ");

}

public static void main(String args[]) {

new ThreadDemo;

}

}

Обратите внимание на то, что цикл внутри метода run выглядит точно так же, как и в предыдущем примере, только на этот раз он выполняется в другом подпроцессе. Подпроцесс main с помощью оператора new Thread(this, "Demo Thread") создает новый объект класса Thread, причем первый параметр конструктора — this — указывает, что мы хотим вызвать метод run текущего объекта. Затем мы вызываем метод start, который запускает подпроцесс, выполняющий метод run. После этого основной подпроцесс (main) переводится в состояние ожидания на три секунды, затем выводит сообщение и завершает работу. Второй подпроцесс — «Demo Thread» — при этом по-прежнему выполняет итерации в цикле метода run до тех пор, пока значение счетчика цикла не уменьшится до нуля. Ниже показано, как выглядит результат работы этой программы после того, как она отработает 5 секунд.

С:\> java ThreadDemo

Thread created: Thread[Demo Thread,5,main]

5

4

3

Выход из main подпроцесса

2

1

Выход из child подпроцесса

10.4. Приоритеты подпроцессов

Если вы хотите добиться от Java предсказуемого, независимого от платформы поведения, вам следует проектировать свои подпроцессы таким образом, чтобы они по своей воле освобождали процессор. Ниже приведен пример с двумя подпроцессами с различными приоритетами, которые не ведут себя одинаково на различных платформах. Приоритет одного из подпроцессов с помощью вызова setPriority устанавливается на два уровня выше Thread. NORM_PRIORITY, то есть умалчиваемого приоритета. У другого подпроцесса приоритет, наоборот, на два уровня ниже. Оба этих подпроцесса запускаются и работают в течение 10 секунд. Каждый из них выполняет цикл, в котором увеличивается значение переменной-счетчика. Через десять секунд после их запуска основной подпроцесс останавливает их работу, присваивая условию завершения цикла while значение «true», и выводит значения счетчиков, показывающих, сколько итераций цикла успел выполнить каждый из подпроцессов.

class Clicker implements Runnable {

int click = 0;

private Thread t;

private boolean running = true;

public clicker(int p) {

t = new Thread(this);

t.setPriority(p);

}

public void run {

while (running) {

click++;

}

}

public void stop {

running = false;

}

public void start {

t.start;

}

}

class HiLoPri {

public static void main(String args[]) {

Thread. currentThread. setPriority(Thread.M AX_PRIORIT Y);

clicker hi = new clicker(Thread.NORM_PRIORITY + 2);

clicker lo = new clicker(Thread.NORM_PRIORITY - 2);

lo.start;

Поделиться с друзьями: