Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

События от панели controlPanel. 2 страница




(int)(Math.random()*w),(int)(Math.random()*h));

}

MultiTask parent; // ссылка на создателя объекта

// этот метод получает управление при запуске потока

public void run()

{ while(true) { draw(); }

}

}

В классе апплета MultiTask объявляется элемент - объект класса Thread:

Thread Lines=null;

Затем в методе start() апплета создается поток Lines, при этом конструктору Thread() передается экземпляр класса DrawLines, реализующего интерфейс Runnable (создание потока с исполняемым адресатом). Далее поток Lines запускается на выполнение:

public void start()

{ if(Rects==null) { Rects=new DrawRects(this); Rects.start(); }

if(Ovals==null) { Ovals=new DrawOvals(this); Ovals.start(); }

if(Lines==null) { Lines=new Thread(new DrawLines(this)); Lines.start(); }

}

Все пооки апплета останавливаются в его методе stop():

public void stop()

{ if(Rects!=null) Rects.stop(); if(Ovals!=null) Ovals.stop();

if(Lines!=null) Lines.stop();

}

2.3 Применение мультизадачности для анимации

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

Работа апплетов основана на обработке событий. Основной (первичный) класс апплета обрабатывает события, переопределяя те или иные методы суперкласса Applet.

Проблема с периодическим обновлением окна апплета возникает из-за того, что в языке Java не предусмотрено никакого механизма для создания генератора событий, способного вызывать какой-то метод класса с заданным интервалом времени.

Перерисовка окна апплета выполняется методом paint(), который вызывается виртуальной машиной Java асинхронно по отношению к выполнению другого кода апплета, если содержимое окна было перекрыто другими окнами.

Возникает вопрос, а можно ли воспользоваться методом paint() для периодической перерисовки окна апплета, организовав в нем, например, бесконечный цикл с задержкой. К сожалению, так поступать нельзя. Метод paint() после перерисовки апплета должен сразу возвратить управление, иначе работа апплета будет заблокирована.

Единственный выход из создавшейся ситуации - создание потока (или нескольких потоков), которые будут выполнять рисование в окне апплета асинхронно по отношению к коду апплета. Например, можно создать поток, который периодически обновляет окно апплета, вызывая для этого метод repaint(), или рисовать из потока непосредственно в окне апплета (в апплете MultiTask использовался именно этот способ).

Если необходимо создать только одну задачу, работающую одновременно с кодом апплетом, то проще выбрать способ реализации многозадачности с использованием интерфейса Runnable для подкласса класса Applet.

Идея заключается в том, что основной класс апплета DoubleTask (пример 2), который является дочерним по отношению к классу Applet, дополнительно реализует интерфейс Runnable, переопределяя метод run() этого интерфейса:

/*------------- Пример 2. Файл DoubleTask.java -------------*/

import java.applet.*;

import java.awt.*;

public class DoubleTask extends Applet implements Runnable

{ public DoubleTask()

{ // здесь можно добавить код конструктора

}

public String getAppletInfo()

{ return "Name: Applet\r\n"; // информация об апплете

}

public void init()

{ resize(320, 240); // установка размера апплета

// здесь можно добавить код инициализации апплета

}

public void destroy()

{ // здесь можно добавить код завершения работы апплета

}

public void paint(Graphics g)

{ // здесь можно добавить код вывода в окно апплета

}

public void start()

{ // создание и запуск потока

if(task==null) { task=new Thread(this); task.start(); }

}

public void stop()

{ // остановка потока

if(task!=null) task.stop();

}

public void run()

{ // здесь можно добавить код, который будет

// выполняться в рамках отдельного потока

}

Thread task=null; // ссылка на поток

// здесь можно добавить специализированный для класса код

}

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

Для создание потока используется оператор new. Поток создается как объект класса Thread, причем конструктору передается ссылка на класс апплета:

task=new Thread(this);

Запуск потока осуществляется методом start для объекта task. При запуске потока начинает работать метод run(), определенный в классе апплета. Причем одновременно с этим код методов апплета также выполняется, так что апплет может обрабатывать различные события в методах обработки событий.

Определим, например, метод paint() апплета следующим образом:

public void paint(Graphics g)

{ g.drawString("Random value "+Math.random(),10,20);

}

А в методе run() реализуем бесконечный цикл, в котором периодически с задержкой 50 миллисекунд вызывается метод repaint(), вызывающий перерисовку апплета:

public void run()

{ while(true)

{

repaint();

try{ Thread.sleep(50); } catch(InterruptedException e) { stop(); }

}

}

Для выполнения задержки метод run() вызывает sleep() класса Thread. Этот метод может вызвать исключение InterruptedException, которое можно обработать с помощью операторов try и catch. В данном случае при возникновении исключения апплет прекращает свою работу.

Такая перерисовка может вызвать мигание окна апплета, поэтому удачной ее назвать нельзя, но этот апплет можно использовать просто как пример реализации «двухзадачности» для апплета.

2.4 Апплет двойного назначения, реализующий интерфейс Runnable

Рассмотрим шаблон апплета двойного назначения, реализующего интерфейс Runnable, создаваемый системой автоматизированной разработки шаблонов апплета Java Аpplet Wizard, встроенной в Microsoft Visual J++. Данный пример во многом похож на пример 2, но новом апплете не только демонстрируется периодическое обновление окна с использованием многозадачности (одновременно с работой апплета выполняется еще одна задача), но и поддерживается возможность работы программы как независимого приложения.

Для создания шаблона апплета Multi (пример 3) среде разработки Microsoft Visual J++ выбрать пункт «New» меню «File». В появившейся диалоговой панели выбрать закладку «Projects» и отметить тип «Java Аpplet Wizard». В поле Name следует ввести имя апплета (Multi). После нажатия на кнопку «Create» на экране появятся по очереди несколько диалоговых панелей, в которой нужно описать создаваемый шаблон апплета.

В первой диалоговой панели в поле «How would you like to be able to run your program» следует включить переключатель «As an applet and as an application». При этом создаваемая программа сможет работать как под управлением WWW-навигатора, так и как самостоятельное приложение.

Система Java Applet Wizard может создать образец документа HTML, в который будет включен разрабатываемый апплет. Для этого во второй диалоговой панели необходимо включить переключатель «Yes, please» в поле «Would you like a sample HTML file».

В третьей диалоговой панели можно указать, будет ли апплет создавать потоки (мультизадачный режим). Так апплет Multi будет создаваться как многозадачный, то в поле «Would you like your applet to be multi-threaded» необходимо включить переключатель «Yes, please».

На вопрос «Would you like support for animation» можно утвердительно ответить только в том случае, если апплет мультизадачный. Но для создаваемого приложения Multi анимация не предполагается поддерживаться, поэтому следует установить переключатель «No, thank you».

Три переключателя, расположенные в поле «Which mouse event handlers would you like added», позволяют автоматически добавить обработчики сообщений от мыши. Для данного приложения следует оставить переключатели невключенными..

С помощью четвертой панели можно указать, какие параметры должны передаваться апплету через документ HTML при запуске. Для приложения Multi никаких параметров передавать не нужно.

В пятой диалоговой панели дается возможность отредактировать информацию о создаваемом апплете. Эта информация будет выдаваться методом getAppInfo(), определенном в классе апплета.

После завершения заполнения последней панели выдается информационное окно, в котором перечисляются заданные ранее параметры приложения. Если нажать кнопку «Ok», то требуемый проект будет создан.

В результате работы системы Java Applet Wizard будет создано три файла с исходными текстами: текст апплета (файл Multi.java и файл MultiFrame.java) и HTML-документ (файл Multi.html).

Рассмотрим тексты создаваемых файлов (комментарии, создаваемые Java Applet Wizard, переведены в данном примере на русский язык). Тексты подобных шаблонных файлов содержатся в Приложении 6 и их можно в дальнейшем использовать в качестве шаблонов апплета двойного назначения, реализующего интерфейс Runnable.

Листинг Java-файла класса апплета:

//*************************************************************

// Multi.java: Applet

//

//*************************************************************

import java.applet.*;

import java.awt.*;

import MultiFrame;

public class Multi extends Applet implements Runnable

{

// Поток, который будет работать одновременно с апплетом

// --------------------------------------------------------------

private Thread m_Multi = null;

// Признак режима работы программы:

// true/false - приложение/апплет

//--------------------------------------------------------------------------

private boolean m_fStandAlone = false;

//--------------------------------------------------------------------------

public static void main(String args[])

{ // Создать рамку (фрейм) для апплета

MultiFrame frame = new MultiFrame("Title");

// До изменения размеров фрейма отобразить его.

// Это необходимо для того, чтобы метод insert()

// выдавал правильные значения

frame.show(); frame.hide();

frame.resize(frame.insets().left + frame.insets().right + 320,

frame.insets().top + frame.insets().bottom + 240);

// Создание объекта апплета, связывание апплета и фрейма

Multi applet_Combi = new Multi();

frame.add("Center", applet_Combi);

// Установление признака режима работы - приложение

applet_Combi.m_fStandAlone = true;

// Вызов методов ааплета для его запуска

applet_Combi.init();

applet_Combi.start();

// Отображение окна фрейма

frame.show();

}

//--------------------------------------------------------------------------

public Multi()

{ // Сделать: Добавьте сюда код конструктора

}

//--------------------------------------------------------------------------

public String getAppletInfo()

{ return "Name: CombiApplet\r\n" +

"";

}

//--------------------------------------------------------------------------

public void init()

{ resize(320, 240);

// Сделать: Добавьте сюда код инициализации

}

//-------------------------------------------------------------------------

public void destroy()

{ // Сделать: Добавьте сюда код завершения работы апплета

}

//--------------------------------------------------------------------------

public void paint(Graphics g)

{ // Сделать: Добавьте сюда код перерисовки окна апплета

g.drawString("Running: " + Math.random(), 10, 20);

}

//--------------------------------------------------------------------------

public void start()

{ // если поток еще не создан, апплет создает

// новый поток как объект класса Thread

if (m_Multi == null)

{ m_Multi = new Thread(this); // создание потока

m_Multi.start(); // запуск потока

}

// Сделать: Добавьте сюда код, который должен

// работать при запуске апплета

}

//--------------------------------------------------------------------------

public void stop()

{ // когда пользователь покидает страницу,

// метод stop() класса Thread останавливает поток

if (m_MultiTask!= null) // если поток был создан

{ m_Multi.stop(); //остановка потока

m_Multi = null; // сброс ссылки на поток

}

// Сделать: Добавьте сюда код, который должен

// работать при остановке апплета

}

// Метод, который работает в рамках отдельного потока.

// Он вызывает периодическое обновление окна апплета

//--------------------------------------------------------------------------

public void run()

{ // выполняем обновление окна в бесконечном цикле

while (true)

{ try

{ // вызов функции обновления

repaint();

// Сделать: Добавьте сюда код, который должен

// здесь работать в рамках отдельного потока

//выполнение небольшой задержки

Thread.sleep(50);

}

catch (InterruptedException e)

{ // Сделать: Добавьте сюда код, который должен

// здесь работать при генерации исключения

// если при выполнении задержки произошло

// исключение, останавливаем работу апплета

stop();

}

}

}

// Сделать: Добавьте сюда код, необходимый для работы

// создаваемого специализированного апплета

Листинг Java-файла класса фрейма для апплета:

import java.awt.*;

//============================================

// Этот класс действует как окно, в котором отображается апплет,

// когда он запускается как обычное приложение

//============================================

class MultiFrame extends Frame

{

// Конструктор класса

//--------------------------------------------------------------------------

public MultiFrame(String str)

{ super (str);

// Сделать: Добавьте сюда код конструктора

}

//--------------------------------------------------------------------------

public boolean handleEvent(Event evt)

{ switch (evt.id)

{ // при закрытии окна завершается работа приложения

//------------------------------------------------------------------

case Event.WINDOW_DESTROY:

// Сделать: Добавьте сюда код, который должен

// работать при остановке приложения

dispose(); // удаление окна

System.exit(0); // завершение приложение

return true;

default:

// передача сообщения на обработку

// методу базового класса

return super.handleEvent(evt);

}

}

}

Листинг HTML-файла:

<html>

<head>

<title> Multi </title>

</head>

<body>

<hr>

<applet

code= Multi.class

name= Multi

width=320

height=240 >

</applet>

<hr>

</body>

</html>

3. Потоки (нити)

Класс Thread содержит несколько конструкторов и большое количество методов для управления потоков.

Некоторые методы класса Thread:

· currentThread - Возвращает ссылку на выполняемый в настоящий момент объект класса Thread

· sleep - Переводит выполняемый в данное время поток в режим ожидания в течение указанного промежутка времени

· start - Начинает выполнение потока. Это метод приводит к вызову соответствующего метода run()

· run - Фактическое тело потока. Этот метод вызывает после запуска потока

· stop - Останавливает поток

· isAlive - Определяет, является ли поток активным (запущенным и не остановленным)

· suspend - Приостанавливает выполнение потока

· resume - Возобновляет выполнение потока. Этот метод работает только после вызова метода suspend()

· setPriority - Устанавливает приоритет потока (принимает значение от MIN_PRIORITY до MAX_PRIORITY)

· getPriority - Возвращает приоритет потока

· wait() - Переводит поток в состояние ожидания выполнения условия, определяемого переменной условия

· join() - Ожидает, пока данный поток не завершит своего существования бесконечно долго или в течении некоторого времени

· setDaemon - Отмечает данный поток как поток-демон или пользовательский поток. Когда в системе останутся только потоки-демоны, программа на языке Java завершит свою работу

· isDaemon - Возвращает признак потока-демона

Для того, чтобы эффективно использовать потоки, необходимо уяснить их различные аспекты, а также особенности работы исполняющей системы языка Java. Рассмотрим атрибуты потоков.

3.1 Состояние потока

Во время своего существования поток может переходить во многие состояния, находясь в одном из нижеперечисленных состояний:

· Новый поток

· Выполняемый поток

· Невыполняемый поток

· Завершенный поток




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


Дата добавления: 2014-11-20; Просмотров: 383; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.129 сек.