Описание исходных текстов аплета Rectangles
В этом приложении мы создаем на базе класса Thread три класса. Первый из них предназначен для создания потока рисования прямоугольников, второй - для создания потока рисования закрашенных эллипсов, а третий - для управления потоком рисования эллипсов. Что же касается основного класса аплета, то он унаследован, как обычно, от класса Applet и не реализует интерфейс Runnable: public class Rectangles
extends Applet
{
. . .
}
Поля класса Rectangles
В классе Rectangles мы определили три поля с именами m_DrawRectThread, m_DrawEllipseThread и m_NotifyTaskThread: DrawRectangles m_DrawRectThread = null; DrawEllipse m_DrawEllipseThread = null; NotifyTask m_NotifyTaskThread = null Эти поля являются ссылками на классы, соответственно DrawRectangles, DrawEllipse и NotifyTask . Первый из них создан для рисования прямоугольников, второй - эллипсов, а третий - для управления потоком рисования эллипсов. Указанные поля инициализируются занчением null, что соответствует неработающим или несозданным задачам. Метод start класса RectanglesЭтот метод последовательно создает три потока и запускает их на выполнение: if(m_DrawRectThread == null)
{
m_DrawRectThread =
new DrawRectangles(this);
m_DrawRectThread.start();
}
if(m_DrawEllipseThread == null)
{
m_DrawEllipseThread =
new DrawEllipse(this);
m_DrawEllipseThread.start();
}
if(m_NotifyTaskThread == null)
{
m_NotifyTaskThread =
new NotifyTask(m_DrawEllipseThread);
m_NotifyTaskThread.start();
}
В качестве параметра конструкторам классов DrawRectangles и DrawEllipse мы передаем ссылку на аплет Rectangles. Эта ссылка будет нужна для получения контекста отображения и рисования геометрических фигур. Поток класса NotifyTask будет управлять работой потока DrawEllipse, поэтому мы передаем его конструктору ссылку на соответствующий объект m_DrawEllipseThread. Метод stop класса RectanglesКогда пользователь покидает страницу сервера Web с аплетом, метод stop класса Rectangles последовательно останавливает gjnjrb рисования прямоугольников и эллипсов, а также управляющий поток: if(m_DrawRectThread != null)
{
m_DrawRectThread.stop();
m_DrawRectThread = null;
}
if(m_DrawEllipseThread == null)
{
m_DrawEllipseThread.stop();
m_DrawEllipseThread = null;
}
if(m_NotifyTaskThread != null)
{
m_NotifyTaskThread.stop();
m_NotifyTaskThread = null;
}
Поля класса DrawRectangles
Класс DrawRectangles определен для потока рисования прямоугольников: class DrawRectangles extends Thread
{
. . .
}
В поле g класа хранится контекст отображения окна аплета, а в поле dimAppWndDimension - размеры этого окна: Graphics g; Dimension dimAppWndDimension; Значения этих полей определяются конструктором класса по ссылке на главный класс аплета. Конструктор класса DrawRectanglesВ качестве параметра конструктору передается ссылка на класс аплета. Конструктор использует эту ссылку для получения и сохранения в полях класса контекста отображения и размеров окна аплета: public DrawRectangles(Applet Appl)
{
g = Appl.getGraphics();
dimAppWndDimension = Appl.getSize();
}
Метод run класса DrawRectangles
Программный код метода run работает в рамках отдельного потока. Он рисует в окне аплета закрашенные прямоугольники. Прямоугольники имеют случайные координаты, расположение и цвет. Для того чтобы рисовать, необходимо получить контекст отображения. Этот контекст был получен конструктором класса DrawRectangles и может быть использован методом run. Вооружившись контекстом отображения и размерами окна аплета, поток входит в бесконечный цикл рисования прямоугольников. В качестве генератора случайных чисел мы используем метод random из класса Math, который при каждом вызове возвращает новое случайное число типа double, лежащее в диапазоне значений от 0.0 до 1.0. Координаты по осям X и Y рисуемого прямоугольника определяются простым умножением случайного числа, полученного от метода random, соответственно, на ширину и высоту окна аплета: x = (int)(dimAppWndDimension.width * Math.random()); y = (int)(dimAppWndDimension.height * Math.random()); Аналогично определяются размеры прямоугольника, однако чтобы прямоугольники не были слишком крупными, мы делим полученные значения на 2: width = (int)(dimAppWndDimension.width * Math.random()) / 2; height = (int)(dimAppWndDimension.height * Math.random()) / 2; Так как случайное число имеет тип double, в обоих случаях мы выполняем явное преобразование результата вычислений к типу int. Для случайного выбора цвета прямоугольника мы вычисляем отдельные цветовые компоненты, умножая значение, полученное от метода random, на число 255: rColor = (int)(255 * Math.random()); gColor = (int)(255 * Math.random()); bColor = (int)(255 * Math.random()); Полученные значения цветовых компонент используются в конструкторе Color для получения цвета. Этот цвет устанавливается в контексте отображения методом setColor: g.setColor(new Color(rColor, gColor, bColor)); Теперь все готово для рисования прямоугольника, которое мы выполняем при помощи метода fillRect: g.fillRect(x, y, width, height); После рисования прямоугольника метод run задерживает свою работу на 50 миллисекунд, вызывая метод sleep: try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
stop();
}
Для обработки исключения InterruptedException, которое может возникнуть во время работы этого метода, мы предусмотрели блок try - catch. При возникновении указанного исключения работа потока останавливается вызовом метода stop. Метод run класса DrawEllipseКласс DrawEllipse очень похож на только что рассмотренный класс DrawRectangles. Отличие есть только в финальном фрагменте метода run, который мы и рассмотрим. Вместо задержки на 50 миллисекунд метод run из класса DrawEllipse переходит в состояние ожидания извещения, вызывая метод wait: try
{
this.wait();
}
catch (InterruptedException e)
{
}
Это извещение создается управляющим потоком класса NotifyTask, к описанию которого мы переходим. Поля класса NotifyTaskВ классе NotifyTask мы определили одно поле STask класса Thread. Это поле которое хранит ссылку на поток, работой которого управляет данный класс: class NotifyTask extends Thread
{
Thread STask;
. . .
}
Конструктор класса NotifyTask
Конструктор класса NotifyTask записывает в поле STask ссылку на задачу рисования эллипсов: public NotifyTask(Thread SynchroTask)
{
STask = SynchroTask;
}
Метод run класса NotifyTask
Метод run класса NotifyTask периодически разблокирует поток рисования эллипсов, вызывая для этого метод notify в цилке с задержкой 30 миллисекунд. Обращение к объекту STask, который хранит ссылку на поток рисования эллипсов, выполняется с использованием синхронизации: public void run()
{
while (true)
{
try
{
Thread.sleep(30);
}
catch (InterruptedException e)
{
}
synchronized(STask)
{
STask.notify();
}
}
}
Поделитесь этой записью или добавьте в закладки |
Полезные публикации |
Главная