Вход/Регистрация
Java: руководство для начинающих
вернуться

Шилдт Герберт

Шрифт:

В приведенном ниже примере программы наличие метода join гарантирует, что основной поток завершит работу последним. // Применение метода join. class MyThread implements Runnable { Thread thrd; // построить новый поток MyThread(String name) { thrd = new Thread(this, name); thrd.start; // начать поток } // начать исполнение нового потока public void run { System.out.println(thrd.getName + " starting."); try { for(int count=0; count < 10; count++) { Thread.sleep(400); System.out.println("In " + thrd.getName + ", count is " + count); } } catch(InterruptedException exc) { System.out.println(thrd.getName + " interrupted."); } System.out.println(thrd.getName + " terminating."); } } class JoinThreads { public static void main(String args[]) { System.out.println("Main thread starting."); MyThread mtl = new MyThread("Child #1"); MyThread mt2 = new MyThread("Child #2"); MyThread mt3 = new MyThread("Child #3"); try { // Ожидание до тех nop, пока указанный метод не завершится. mtl.thrd.join; System.out.println("Child #1 joined."); mt2.thrd.join ; System.out.println("Child #2 joined."); mt3.thrd.join; System.out.println("Child #3 joined."); } catch(InterruptedException exc) { System.out.println("Main thread interrupted."); } System.out.println("Main thread ending."); } }

Результат выполнения данной программы приведен ниже. Вследствие отличий в вычислительных средах он может получиться у вас несколько иным. Main thread starting. Child #1 starting. Child #2 starting. Child #3 starting. In Child #2, count is 0 In Child #1, count is 0 In Child #3, count is 0 In Child #2, count is 1 In Child #3, count is 1 In Child #1, count is 1 In Child #2, count is 2 In Child #1, count is 2 In Child #3, count is 2 In Child #2, count is 3 In Child #3, count is 3 In Child#1, count is 3 In Child #3, count is 4 In Child #2, count is 4 In Child #1, count is 4 In Child #3, count is 5 In Child #1, count is 5 In Child #2, count is 5 In Child #3, count is 6 In Child #2, count is 6 In Child #1, count is 6 In Child #3, count is 7 In Child #1, count is 7 In Child #2, count is 7 In Child #3, count is 8 In Child #2, count is 8 In Child #1, count is 8 In Child #3, count is 9 Child #3 terminating. In Child #2, count is 9 Child #2 terminating. In Child #1, count is 9 Child #1 terminating. Child #1 joined. Child #2 joined. Child #3 joined. Main thread ending.

Как видите, после того как вызываемый метод j oin возвращает управление, исполнение потока прекращается. Приоритеты потоков

У каждого потока имеется свой приоритет, который отчасти определяет, насколько часто поток получает доступ к ЦП. Вообще говоря, низкоприоритетные потоки получают доступ к ЦП реже, чем высокоприоритетные. Таким образом, в течение заданного промежутка времени низкоприоритетному потоку будет доступно меньше времени ЦП, чем высокоприоритетному. Как и следовало ожидать, время ЦП, получаемое потоком, оказывает определяющее влияние на характер его исполнения и взаимодействия с другими потоками, исполняемыми в настоящий момент в системе.

Следует иметь в виду, что, помимо приоритета, на частоту доступа потока к ЦП оказывают влияние и другие факторы. Так, если высокоприоритетный поток ожидает доступа к некоторому ресурсу, например для ввода с клавиатуры, он блокируется, а вместо него исполняется низкоприоритетный поток. Но когда высокоприоритетный поток получит доступ к ресурсам, он прервет низкоприоритетный поток и возобновит свое исполнение. На планирование работы потоков оказывает также влияние способ, посредством которого в операционной системе поддерживается многозадачность (см. врезку “Обращение к знатоку” в конце этого раздела). Следовательно, если один поток имеет более высокий приоритет, чем другой поток, это еще не означает, что первый поток будет исполняться быстрее второго. Высокий приоритет потока лишь означает, что потенциально он может получить больше времени ЦП.

При запуске порожденного потока его приоритет устанавливается равным приоритету родительского потока. Изменить приоритет можно, вызвав метод setPriority из класса Thread. Ниже приведено объявление этого метода, final void setPriority(int уровень)

В качестве параметра уровень данному методу передается новый приоритет для потока. Значение параметра уровень должно находиться в пределах от MIN PRIORITY до MAX PRIORITY. В настоящее время этим константам соответствуют числовые значения от 1 до 10. Для того чтобы восстановить приоритет потока по умолчанию, следует указать значение 5, которому соответствует константа N0RM PRI0RITY. Константы, определяющие приоритеты потоков, определены как static final в классе Thread.

Получить текущий приоритет можно с помощью метода getPriorityO из класса Thread, объявляемого следующим образом: final int getPriority

Ниже приведен пример программы, демонстрирующий использование двух потоков с разными приоритетами. Потоки создаются как экземпляры класса Priority. В методе run содержится цикл, отсчитывающий число своих шагов. Этот цикл завершает работу, когда значение счетчика достигает 10000000 или же когда статическая переменная stop принимает логическое значение true. Первоначально переменной stop присваивается логическое значение false, но первый же поток, заканчивающий отсчет, устанавливает в ней логическое значение true. В результате второй поток завершится, как только ему будет выделен квант времени. В цикле производится проверка символьной строки в переменной currentName на совпадение с именем исполняемого потока. Если они не совпадают, это означает, что произошло переключение задач. При этом отображается имя нового потока, которое присваивается переменной currentName. Это дает возможность следить за тем, насколько часто каждый поток получает время ЦП. После остановки обоих потоков выводится число шагов, выполненных в каждом цикле. // Демонстрация потоков с разными приоритетами. class Priority implements Runnable { int count; Thread thrd; static boolean stop = false; static String currentName; /* Построение нового потока. Обратите внимание на то, что конструктор не запускает поток на исполнение. */ Priority(String name) { thrd = new Thread(this, name); count = 0; currentName = name; } // начать исполнение нового потока public void run { System.out.println(thrd.getName + " starting."); do { count++; if(currentName.compareTo(thrd.getName) != 0) { currentName = thrd.getName; System.out.println("In " + currentName); } // Первый же поток, в котором достигнуто значение 10000000, // завершает остальные потоки. } while(stop == false && count < 10000000); stop = true; System.out.println("\n" + thrd.getName + " terminating."); } } class PriorityDemo { public static void main(String args[]) { Priority mtl = new Priority("High Priority"); Priority mt2 = new Priority("Low Priority"); // задать приоритеты // Поток mtl получает более высокий приоритет, чем поток mt2. mtl.thrd.setPriority(Thread.NORM_PRIORITY+2); mt2.thrd.setPriority(Thread.NORM_PRIORITY-2); // запустить потоки на исполнение mtl.thrd.start; mt2.thrd.start; try { mtl.thrd.join; mt2.thrd.join; } catch(InterruptedException exc) { System.out.println("Main thread interrupted."); } System.out.println("\nHigh priority thread counted to " + mtl.count); System.out.println("Low priority thread counted to " + mt2.count); } }

Результат выполнения данной программы выглядит следующим образом: High Priority starting. In High Priority Low Priority starting. In Low Priority In High Priority High Priority terminating. Low Priority terminating. High priority thread counted to 10000000 Low priority thread counted to 8183

В данном примере большую часть времени ЦП получает высокоприоритетный поток. Очевидно, что результат выполнения программы существенно зависит от быстродействия ЦП и их количества, типа операционной системы и наличия прочих задач, выполняющихся в системе. Синхронизация

Если в программе используется несколько потоков, то иногда приходится координировать действия двух потоков или более. Процесс достижения такой координации называется синхронизацией. Самой распространенной причиной для синхронизации является необходимость разделять среди двух или более потоков общий ресурс, который может быть одновременно доступен только одному потоку. Например, когда в одном потоке выполняется запись информации в файл, второму потоку должно быть запрещено делать это в тот же самый момент времени. Синхронизация требуется и в том случае, если один поток ожидает событие, вызываемое другим потоком. В подобной ситуации требуются какие-то средства, позволяющие приостановить один из потоков до тех пор, пока не произойдет событие в другом потоке. После этого ожидающий поток может возобновить свое выполнение.

  • Читать дальше
  • 1
  • ...
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: