Выбрать главу

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

Для поддержки многопоточного программирования в Java предусмотрен класс и интерфейс . Для поддержки многопоточного программирования в Java предусмотрен класс Thread и интерфейс Runnable.

В каких случаях следует отдать предпочтение расширению класса Thread над реализацией интерфейса Runnable? Подклассы, производные от класса Thread, целесообразно создавать в тех случаях, когда, помимо метода run (), требуется переопределить другие методы данного класса.

Покажите, как с помощью метода j о in () можно организовать ожидание завершения потокового объекта MyThrd. MyThrd.join()

Покажите, как установить приоритет потока MyThrd на три уровня выше нормального приоритета. MyThrd.setPriority(Thread.N0RM_PRI0RITY+3);

Что произойдет, если в объявлении метода указать ключевое слово synchronized? Если указать ключевое слово synchronized в объявлении метода, то в каждый момент времени этот метод будет вызываться только в одном потоке для любого заданного объекта его класса.

Методы wait () и notify () служат для . взаимодействия потоков

Внесите в класс TickTock изменения для организации настоящего отчета времени. Первую половину секунды должен занимать вывод на экран слова "Tick", а вторую — вывод слова "Tock". Таким образом, сообщение "Tick-Tock" должно соответствовать одной секунде отсчитываемого времени. (Время переключения контекстов можно не учитывать.) Для организации отчета времени достаточно ввести в классе TickTock вызовы метода sleep (), как показано ниже. // Вариант класса TickTock, в который введены вызовы // метода sleep() для организации отсчета времени. class TickTock { String state; // Состояние часов synchronized void tick(boolean running) { 582 Javc,/: руководство для начинающих, 5-е издание if(!running) { // остановить часы state = "ticked"; notifyO; // уведомить ожидающие потоки return; } System.out.print("Tick "); // ожидать 1/2 секунды try { Thread.sleep(500); } catch(InterruptedException exc) { System.out.println("Thread interrupted."); } state = "ticked"; // установить текущее состояние после такта "тик" notifyO; // разрешить выполнение метода tock() try { while(!state.equals("tocked")) wait (); // ожидать завершения метода tock() } catch(InterruptedException exc) { System.out.println("Thread interrupted."); } synchronized void tock(boolean running) { if(!running) { // остановить часы state = "tocked"; notifyO; // уведомить ожидающие потоки return; } System.out.println("Tock"); // ожидать 1/2 секунды try { Thread.sleep(500); } catch(InterruptedException exc) { System.out.println("Thread interrupted."); } state = "tocked"; // установить текущее состояние после такта "так" notifyO; // разрешить выполнение метода tick() try { while(!state.equals("ticked")) wait (); // ожидать завершения метода tick() } catch(InterruptedException exc) { System.out.println("Thread interrupted."); } Приложение А. Ответы на вопросы для самопроверки 583 } }

Почему в новых программах на Java не следует применять методы suspend (), resume() и stop()? Методы suspend (), resume () и stop () не рекомендуется применять, поскольку они могут стать причиной серьезных осложнений при выполнении программы.

С помощью какого метода из класса Thread можно получить имя потока? С помощью метода getName ().

Какое значение возвращает метод is Alive () ? Он возвращает логическое значение true, если вызывающий поток исполняется, или логическое значение false, если поток завершен. Глава 12. Перечисления, автоупаковка,

статический импорт и аннотации

Константы перечислимого типа иногда называются самотипизированными. Что это означает? Часть “само” в термине самотипизированный означает тип перечисления, в котором определена константа. Следовательно, константа перечислимого типа является объектом того перечисления, в которое она входит.

Какой класс автоматически наследуют перечисления? Все перечисления наследуют от класса Enum.

Напишите для приведенного ниже перечисления программу, в которой метод values () служит для отображения списка констант и их значений. enum Tools { SCREWDRIVER, WRENCH, HAMMER, PLIERS } Это задание имеет следующее решение: enum Tools { SCREWDRIVER, WRENCH, HAMMER, PLIERS } class ShowEnum { public static void main(String args[]) { for(Tools d : Tools.values()) System.out.print(d + " has ordinal value of " + d.ordinal() + '\n'); } }

Программу, имитирующую автоматизированный светофор и созданную в примере для опробования 12.1, можно усовершенствовать, внеся ряд простых изменений, чтобы выгодно воспользоваться возможностями перечислений. В исходной версии этой программы продолжительность отображения каждого цвета светофора регулировалась в классе Traf ficLightSimulator, причем величины задержек были жестко запрограммированы в методе run (). Измените исходный код программы 584 Jav\, 7: руководство для начинающих, 5-е издание таким образом, чтобы продолжительность отображения каждого цвета светофора задавалась константами перечислимого типа Traf f icLightColor. Для этого вам понадобятся конструктор, переменная экземпляра, объявленная как private, а также метод getDelay (). Подумайте о том, как еще можно улучшить данную программу. (Подсказка: попробуйте отказаться от оператора switch и воспользоваться порядковыми значениями каждого цвета для переключения светофора.) Усовершенствованная версия программы, имитирующей работу светофора, приведена ниже. В нее внесены два существенных изменения. Во-первых, величина задержки переключения связана теперь со значением перечислимого типа, что улучшает структуру кода. И во-вторых, в методе run () удалось обойтись без оператора switch. Вместо этого методу sleep () теперь передается вызов tic. getDelay (), и благодаря этому автоматически устанавливается задержка, соответствующая текущему цвету светофора. // Усовершенствованная версия программы, имитирующей работу светофора. // Величины задержки теперь хранятся в классе TrafficLightColor. // Перечисление цветов переключения светофора, enum TrafficLightColor { RED(12000), GREEN(10000), YELLOW(2000); private int delay; TrafficLightColor(int d) { delay = d; } int getDelay() { return delay; } } // Имитация автоматизированного светофора, class TrafficLightSimulator implements Runnable { private Thread thrd; // Поток для имитации светофора private TrafficLightColor tic; // Текущее значение цвета boolean stop = false; // Остановка имитации, если истинно boolean changed = false; // Переключение светофора, если истинно TrafficLightSimulator(TrafficLightColor init) { tic = init; thrd = new Thread(this); thrd.start(); } TrafficLightSimulator() { tic = TrafficLightColor.RED; thrd = new Thread(this); thrd.start(); } // Запуск имитации автоматизированного светофора. Приложение А. Ответы на вопросы для самопроверки 585 public void run() { while(!stop) { // По сравнению с предыдущей версией программы // код значительно упростился! try { Thread.sleep(tlc.getDelay()); } catch(InterruptedException exc) { System.out.println(exc); } changeColor (); } } // Переключение цвета светофора, synchronized void changeColor() { switch(tic) { case RED: tic = TrafficLightColor.GREEN; break; case YELLOW: tic = TrafficLightColor.RED; break; case GREEN: tic = TrafficLightColor.YELLOW; } changed = true; notify(); // уведомить о переключении цвета светофора } // Ожидание переключения цвета светофора, synchronized void waitForChange() { try { while(!changed) wait(); // ожидать переключения цвета светофора changed = false; } catch(InterruptedException exc) { System.out.println(exc); } } // Возврат текущего цвета. TrafficLightColor getColor() { return tic; } // Прекращение имитации светофора, void cancel() { stop = true; class TrafficLightDemo { public static void main(String args[]) { TrafficLightSimulator tl = new TrafficLightSimulator(TrafficLightColor.GREEN); for(int i=0; i < 9; i++) { System.out.println(tl.getColor()); tl.waitForChange(); } tl.cancel (); } }

Что такое упаковка и распаковка? В каких случаях производится автоупаковка и автораспаковка? Упаковка означает включение значения простого типа в объект оболочки, а распаковка — извлечение значения из объекта оболочки. Автоупаковка означает автоматическую упаковку значения без явного создания объекта, тогда как при автораспаковке значение простого типа автоматически извлекается из объекта оболочки без явного вызова соответствующего метода, например intValue ().

Измените следующий фрагмент кода таким образом, чтобы в нем производилась автоупаковка: Short val = new Short(123); Это задание имеет следующее решение: Short val = 123;