Оглавление

Многопоточность
Процессы, потоки и приоритеты
Многопоточность в Java
Многопоточность и анимация
Синхронизация потоков
Потоки-демоны
Аплет Rectangles
Исходные тексты
Описание текстов

    Описание исходных текстов аплета 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();
        }
      }
    }


Java | Продукты и решения | Технологии | Сервис и обучение
О компании | Партнеры | Новости | Поиск
Sun Microsystems Inc. Corporate Information Our partners News and Events Search on site Java Computing Products and Solutions Technologies and Researches Education and Service Content



Сайт создан в системе uCoz