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

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

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

Назад Вперед

6.3. Управление потоками

Пример демонстрирует простейшие методы управления потоками - останов, продолжение работы, изменение текущего приоритета.

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

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

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

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

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

В этом разделе библиотеки примеров мы продемонстрируем использование методов start, stop, а также метода setPriority, предназначенного для изменения приоритета потока.

Что касается методов start и stop, то вы с ними уже встречались в предыдущих примерах этого раздела библиотекиа примеров. Метод setPriority используется очень просто, например:

myThread.setPriority(Thread.MIN_PRIORITY);

В качестве параметра мы передаем методу одну из нескольких констант, определенных в классе Thread. Возможны следующие значения:

 

Значение Приоритет
Thread.NORM_PRIORITY Нормальный
Thread.MIN_PRIORITY Минимальный
Thread.MAX_PRIORITY Максимальный

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

Окно аплета Rectangles, исходные тексты которого мы опишем в этом разделе, показано на рис. 1.

pic1.gif (8842 bytes)

Рис. 1. Окно аплета Rectangles

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

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

Установив курсор в область панели и нажав любую клавишу мыши, вы можете остановить работу соответствующего потока. При отпускании клавиши поток продолжит свое выполнение.

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

Главный класс нашего аплета создан на базе класса Applet:

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

public class Rectangles extends Applet 
{
  . . .
}

В нем мы определили одно поле rp и несколько методов.

Поле rp - это массив, хранящий ссылки на панели класса RectPanel, определенного в нашем приложении:

RectPanel[] rp;
Метод init

При инициализации аплета метод init вначале устанавливает режим размещения компонент GridLayout:

setLayout(new GridLayout(0, 3));

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

Панели создаются и добавляются следующим образом:

rp = new RectPanel[9];
    
for(int i = 0; i < 9; i++)
{
  rp[i] = new RectPanel();
  add(rp[i]);
}
Метод start

Когда аплет активизируется, метод start вызывает для каждой панели метод startThread, определенный в классе RectPanel:

public void start()
{
  for(int i = 0; i < 9; i++)
    rp[i].startThread();
}

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

Метод stop

Если аплет становится неактивным, метод stop останавливает все потоки, работающие в панелях:

public void stop()
{
  for(int i = 0; i < 9; i++)
    rp[i].stopThread();
}

Для этого вызывается метод stopThread, определенный в классе RectPanel.

Класс RectPanel

Класс RectPanel создан на базе класса Panel:

class RectPanel extends Panel
  implements Runnable, MouseListener

{
  . . .
}

Дополнительно он реализует интерфейсы Runnable и MouseListener. Первый из них нужен для организации многопоточного режима работы, а второй - для обработки событий от мыши.

В классе RectPanel мы определили два поля:

Dimension dm;
Thread tiktak = null;

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

Конструктор класса RectPanel

Этот конструктор очень прост:

public RectPanel()
{
  tiktak = null;
  this.addMouseListener(this);
}

Он записывает в поле tiktak значение null, а затем регистрирует обработчик событий от мыши.

Метод paint

В задачу метода paint входит определение текущих размеров окна панели и рисование тонкой рамки вокруг этого окна:

public void paint(Graphics g)
{
  dm = getSize();
  g.drawRect(
    0, 0, dm.width - 1, dm.height - 1);
}

Заметим, что метод paint не рисует прямоугольники. Это делает метод run.

Метод startThread

Когда аплет активизируется, он запускает потоки панелей, вызывая для каждой панели метод startThread:

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

Здесь мы просто создаем новый поток как объект класса Thread, передавая конструктору ссылку на объект класса RectPanel, а затем запускаем этот поток.

Метод stopThread

Метод stopThread выполняет остановку работающего потока методом stop:

public void stopThread()
{
  if(tiktak != null)
  {
    tiktak.stop();
    tiktak = null;
  }
}
Метод run

На метод run возлагается задача рисования цветных прямоугольников в окне панели.

В теле этого метода мы определили несколько переменных.

В переменной g хранится контекст отображения, полученный для окна панели.

Graphics g = getGraphics();

Переменные rColor, gColor и bColor хранят текущий цвет прямоугольника:

int rColor, gColor, bColor;

В следующих переменных хранятся координаты и размеры текущего отображаемого прямоугольника:

int x, y, width, height;

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

while(true)
{
  . . .
}

Прежде всего мы определяем, было ли уже нарисовано окно панели. Для этого достаточно проверить содержимое поля dm, хранящего размеры окна панели, так как это поле инициализируется методом paint:

if(dm != null)
{
  . . .
  // рисование прямоугольника
}

Прямоугольник рисуется только в том случае, если содержимое поля dm не равно null.

Перед рисованием метод run определяет координаты и размеры прямоугольника:

x = (int)((dm.width + 1) * 
  Math.random());
y = (int)((dm.height + 1) * 
  Math.random());
      
width = (int)((dm.width - 2) * 
  Math.random()) / 2;
height = (int)((dm.height - 2)* 
  Math.random()) / 2;

Далее метод run случайным образом выбирает цвет прямоугольника и устанавливает его в контексте отображения панели:

rColor = (int)(255 * Math.random());
gColor = (int)(255 * Math.random());
bColor = (int)(255 * Math.random());
      
g.setColor(
  new Color(rColor, gColor, bColor));

Прямоугольник рисуется методом fillRect:

g.fillRect(x, y, width, height);

В конце каждой итерации бесконечного цикла выполняется задержка на 10 миллисекунд:

try
{
  tiktak.sleep(10);
}
catch(InterruptedException ie)
{
  tiktak.stop();
}
Метод mousePressed

Когда пользователь нажимает клавишу мыши в окне панели, управление передается методу mousePressed. Наша реализация этого метода останавливает текущий поток, связанный с данной панелью, методом stop:

public void mousePressed(MouseEvent e)
{
  if(tiktak != null)
  {
    tiktak.stop();
    tiktak = null;
  }
}
Метод mouseReleased

Если после остановки потока возобновить его выполнение, отжав клавишу мыши, управление будет передано методу mouseReleased. Этот метод создаст поток заново и запустит его на выполнение:

public void mouseReleased(MouseEvent e)
{
  if(tiktak == null)
  {
    tiktak = new Thread(this);
    tiktak.start();
  }
}
Метод mouseEntered

При помещении курсора в область панели метод mouseEntered снизит приоритет потока, связанного с данной панелью:

public void mouseEntered(MouseEvent e)
{
  if(tiktak != null)
  {
    tiktak.setPriority(Thread.MIN_PRIORITY);
  }  
}

Для этого будет вызван метод setPriority с параметром Thread.MIN_PRIORITY.

Метод mouseExited

Метод mouseExited, получающий управление при выходе курсора за пределы окна панели, восстанавливает нормальный приоритет потока, связанного с данной панелью:

public void mouseExited(MouseEvent e)
{
  if(tiktak != null)
  {
    tiktak.setPriority(Thread.NORM_PRIORITY);
  }  
}
Метод mouseClicked

Этот метод нами не используется, но определен как часть интерфейса MouseListener:

public void mouseClicked(MouseEvent e)
{
}

Назад Вперед

[Назад]