Назад
Вперед
6.2. Создание двух потоков
Пример демонстрирует использование
многопоточности для динамического изменения
цвета и размера текстовой строки. Первый поток
устанавливает цвет, а второй - размер.
Исходный текст примера
Архив проекта для Java WorkShop 2.0
Демонстрация
(ваш браузер должен уметь работать с аплетами
Java JDK 1.1)
Немного теории
Когда в аплете необходимо создать несколько
потоков, вместо интерфейса Runnable удобнее
применить другую технику. Эта техника
предусматривает создание собственных классов на
базе класса Thread.
В каждом классе, созданном на базе класса Thread,
вы должны предусмотреть метод run, например:
class MyThread extends Thread
{
. . .
public void run()
{
. . .
}
}
Этот метод будет работать в рамках отдельного
потока.
Описание примера
Наш второй пример похож на предыдущий, однако
наряду с хаотическим изменением цвета строки в
нем меняется и размер символов (рис. 1).
Рис. 1. Изменяется цвет и размер символов
Этот размер сначала плавно увеличивается от 12
пунктов до 30 пунктов, а потом так же плавно
уменьшается до прежнего значения.
Перейдем к описанию исходного текста аплета.
Главный класс аплета
Главный класс аплета не имеет никаких
особенностей и создан на базе класса Applet:
import java.applet.Applet;
import java.awt.*;
public class Multi2 extends Applet
{
. . .
}
Заметим, что он не реализует интерфейс Runnable.
Для хранения ссылок на потоки в главном классе
мы предусмотрели два поля:
Thread thrColor = null;
Thread thrSize = null;
Первое из них хранит ссылку на поток,
изменяющий цвет символов, а второе - на поток,
изменяющий размер символов.
Текущие значения компонентов цвета находятся в
полях rColor, gColor и bColor:
int rColor, gColor, bColor;
Текущий размер символов записан в поле nFontSize:
int nFontSize = 12;
Метод start
При активизации аплета метод start
последовательно создает и запускает на
выполнение два потока:
public void start()
{
if(thrColor == null)
{
thrColor = new ColorThread(this);
thrColor.start();
}
if(thrSize == null)
{
thrSize = new SizeThread(this);
thrSize.start();
}
}
Поток управления размером символов создается
как объект класса SizeThread, а поток управления
цветом - как объект класса SizeThread. Оба класса
образованы в нашем приложении на базе класса Thread.
Метод stop
Этот метод получает управление, когда аплет
переводится в неактивное состояние. В его задачу
входит остановка работы потоков:
public void stop()
{
if(thrColor != null)
{
thrColor.stop();
thrColor = null;
}
if(thrSize != null)
{
thrSize.stop();
thrSize = null;
}
}
После остановки потоков метод записывает в
соответствующие поля значение null.
Метод paint
Исходный текст этого метода аналогичен
описанному в предыдущем примере за одним
исключением - при выборе шрифта размер символов
берется из поля nFontSize:
g.setFont(new Font("Courier",
Font.PLAIN, nFontSize));
Класс ColorThread
Класс ColorThread создан на базе класса Thread:
class ColorThread extends Thread
{
. . .
}
Он предназначен для создания потока,
отвечающего за изменение цвета текстовой строки,
отображаемой в окне аплета.
В классе определено одно поле и два метода.
Поле c с именем a хранит ссылку на аплет, то есть
на объект главного класса аплета Multi2:
Multi2 a = null;
Это поле инициализируется конструктором
класса SizeThread:
public ColorThread(Applet appl)
{
a = (Multi2)appl;
}
Как видите, инициализация сводится к записи в
поле значения, передаваемого конструктору в
качестве параметра.
Что же касается метода run, определенного в
классе ColorThread, то он почти полностью аналогичен
методу run из предыдущего примера:
public void run()
{
while(true)
{
a.rColor = (int)(255 * Math.random());
a.gColor = (int)(255 * Math.random());
a.bColor = (int)(255 * Math.random());
a.repaint();
try
{
Thread.sleep(1000);
}
catch(InterruptedException ie)
{
stop();
}
}
}
Обратите внимание на отличие: обращение к полям
главного класса аплета и методу repaint выполняется
через ссылку, записанную в переменной с именем a.
Класс SizeThread
Этот класс также создан на базе класса Thread:
class SizeThread extends Thread
{
Multi2 a = null;
public SizeThread(Applet appl)
{
a = (Multi2)appl;
}
public void run()
{
. . .
}
}
Конструктор класса получает в качестве
параметра ссылку на аплет и сохраняет ее в поле с
именем a.
Займемся теперь методом run класса SizeThread. Как мы
говорили раньше, он предназначен для плавного
изменения размеров символов.
Направление изменения размеров хранится в поле
incr:
boolean incr = true;
Когда здесь хранится значение true, размеры
увеличиваются, а когда false - уменьшаются.
Вся работа выполняется в бесконечном цикле:
while(true)
{
. . .
}
При каждой итерации проверяется флаг incr, после
чего соответствующим образом изменяется высота
символов, записанная в поле nFontSize:
if(incr)
{
if(a.nFontSize < 30)
a.nFontSize++;
else
incr = false;
}
else
{
if(a.nFontSize > 12)
a.nFontSize--;
else
incr = true;
}
Далее окно аплета перерисовывается:
a.repaint();
Перед повторением итерации выполняется
задержка на 100 миллисекунд:
try
{
Thread.sleep(100);
}
catch(InterruptedException ie)
{
stop();
}
Назад Вперед |