Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых
[Назад]

Библиотека примеров приложений Java

Оглавление
Простейший пример
Создание двух потоков
Управление потоками
Спрайтовая анимация
Панели с двигающимся текстом
Бегущая строка с мерцанием
Устранение мерцания
Поток для записи в файл
Контроль за выводом в файл
Чтение с сервера Web

Назад Вперед

6.1. Простейший пример

Пример демонстрирует использование многопоточности для динамического изменения цвета текстовой строки.

Исходный текст примера

Архив проекта для Java WorkShop 2.0

Демонстрация
(ваш браузер должен уметь работать с аплетами Java JDK 1.1)

Немного теории

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

Почему так происходит?

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

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

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

Например, для запуска потока на выполнение предусмотрен метод start, а для его остановки - метод stop. Метод sleep, имеющийся в классе Thread, позволяет задержать работу потока на заданный период времени. Полное описание этих методов вы найдете в документации JDK.

Описание примера

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

pic1.gif (2469 bytes)

Рис. 1. Строка периодически изменяет свой цвет

Заметим, что в строке записаны численные значения компонент цвета.

Как выглядит исходный текст аплета и как он работает?

Главный класс аплета

Главный класс аплета реализует интерфейс Runnable:

import java.applet.Applet;
import java.awt.*;

public class Multi1 extends Applet
  implements Runnable
{
  . . .
  public void run()
  {
    . . .
  }
}

Помимо методов, обычных для однопоточных аплетов, в этом классе мы определили метод run, работающий как отдельный поток.

В главном классе нашего аплета предусмотрены следующие поля:

Thread thr = null;
int rColor, gColor, bColor;

В поле thr класса Thread хранится ссылка на поток, в рамках которого выполняется метод run. Первоначально это поле инициализируется значением null.

Поля rColor, gColor, bColor хранят текущие значения компонент цвета текстовой строки, отображаемой в окне аплета.

Метод start

Метод start вызывается при активизации аплета. Его задачей является создание дополнительного потока и запуск этого потока на выполнение:

public void start()
{
  if(thr == null)
  {
    thr = new Thread(this);
    thr.start();
  }
}

Поток создается с помощью конструктора класса Thread. При этом в качестве параметра конструктору передается ссылка на главный класс аплета, в котором определен метод run.

После вызова метода start наряду с главным потоком, в рамках которого выполняется основной код аплета, запускается дополнительный поток. Его код находится в определении метода run.

Метод stop

Если пользователь покидает страницу HTML с аплетом, происходит вызов метода stop.

Обычно в многопоточных аплетах этот метод останавливает работу всех запущенных потоков. Наш метод поступает таким же образом:

public void stop()
{
  if(thr != null)
  {
    thr.stop();
    thr = null;
  }
}

После остановки потока он записывает в поле thr значение null. Если аплет будет снова активизирован, поток снова запустится методом start, определенным в главном классе аплета.

Метод run

Как мы уже говорили, метод run работает как отдельный поток. Основной код аплета никогда напрямую не должен вызывать этот метод. Для запуска потока на выполнение в классе Thread предусмотрен метод start.

Наш метод run представляет собой бесконечный цикл:

public void run()
{
  while(true)
  {
    . . .
  }
}

Если этот цикл завершится, поток также прекратит свою работу.

Какие действия выполняются внутри цикла?

Прежде всего мы получаем три случайные компоненты цвета:

rColor = (int)(255 * Math.random());
gColor = (int)(255 * Math.random());
bColor = (int)(255 * Math.random());

На следующем этапе метод run вызывает метод repaint:

repaint();

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

Перед тем как сделать следующую итерацию, мы выполняем задержку работы потока на 1000 миллисекунд:

try
{
  thr.sleep(1000);
}
catch(InterruptedException ie)
{
  stop();
}

Для этого мы вызываем метод sleep, предусмотренный в классе Thread. Регулируя задержку, вы можете влиять на скорость перерисовки текстовой строки.

При работе метода sleep возможно возникновение исключения InterruptedException (если задержка будет по каким-либо причинам прервана). В этом аварийном случае мы останавливаем работу потока.

Метод paint

Так как метод run, запущенный в отдельном потоке, вызывает каждую секунду метод repaint, с этой же периодичностью будет вызываться метод paint.

Получив управление, метод paint устанавливает в контексте отображения цвет, компоненты которого хранятся в полях rColor, gColor и bColor:

String s;
g.setColor(
  new Color(rColor, gColor, bColor));

Напомним, что метод run периодически изменяет значения компонент цвета случайным образом.

Далее метод paint формирует текстовую строку, устанавливает шрифт Courier и затем рисует эту строку в окне аплета:

s = "(R, G, B) = (" + rColor + ", " + 
  gColor + ", " + bColor + ")";
      
g.setFont(
  new Font("Courier", Font.PLAIN, 12));
      
g.drawString(s, 10, 30);

Заметим, что достигнутый в нашем аплете эффект не может быть получен без применения многопоточности. В частности, ни в коем случае нельзя организовывать бесконечный цикл внутри метода paint. Такая попытка приведет лишь к "зависанию" аплета.


Назад Вперед

[Назад]