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

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

Оглавление
Простейший пример
Создание двух потоков

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

Назад Вперед

6.2. Создание двух потоков

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

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

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

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

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

Когда в аплете необходимо создать несколько потоков, вместо интерфейса Runnable удобнее применить другую технику. Эта техника предусматривает создание собственных классов на базе класса Thread.

В каждом классе, созданном на базе класса Thread, вы должны предусмотреть метод run, например:

class MyThread extends Thread
{
  . . .
  public void run()
  {
    . . .
  }
}

Этот метод будет работать в рамках отдельного потока.

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

Наш второй пример похож на предыдущий, однако наряду с хаотическим изменением цвета строки в нем меняется и размер символов (рис. 1).

pic1.gif (3134 bytes)

Рис. 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();
}

Назад Вперед

[Назад]