Информатика и информационные технологии Электротехника История искусства Каталог графических примеров

Реализация многопоточности в Java

Назад Вперед
должны воспользоваться классом java.lang.Thread . В этом классе определены все методы, необходимые для создания потоков, управления их состоянием и синхронизации.

Как пользоваться классом Thread ?

Есть две возможности.

Второй способ особенно удобен в тех случаях, когда ваш класс должен быть унаследован от какого-либо другого класса (например, от класса Applet) и при этом вам нужна многопоточность. Так как в языке программирования Java нет множественного наследования, невозможно создать класс, для которого в качестве родительского будут выступать классы Applet и Thread. В этом случае реализация интерфейса Runnable является единственным способом решения задачи.

Методы класса Thread

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

С помощью конструкторов вы можете создавать потоки различными способами, указывая при необходимости для них имя и группу. Имя предназначено для идентификации потока и является необязательным атрибутом. Что же касается групп, то они предназначены для организации защиты потоков друг от друга в рамках одного приложения.

Методы класса Thread предоставляют все необходимые возможности для управления потоками, в том числе для их синхронизации.

Поля

Три статических поля предназначены для назначения приоритетов потокам.

Нормальный

public 
final static int NORM_PRIORITY;

Максимальный

public 
final static int MAX_PRIORITY;

Минимальный

public 
final static int MIN_PRIORITY;

Конструкторы

Создание нового объекта Thread

public Thread();

Создвание нового объекта Thread с указанием объекта, для которого будет вызываться метод run

public Thread(Runnable target);

Аналогично предыдущему, но дополнительно задается имя нового объекта Thread

public 
Thread(Runnable target, String name);

Создание объекта Thread с указанием его имени

public Thread(String name);

Создание нового объекта Thread с указанием группы потока и объекта, для которого вызывается метод run

public Thread(ThreadGroup group, Runnable 
target);

Аналогично предыдущему, но дополнительно задается имя нового объекта Thread

public Thread(ThreadGroup 
group, Runnable target, String name);

Создание нового объекта Thread с указанием группы потока и имени объекта

public 
Thread(ThreadGroup group, String name);

Методы

Текущее количество активных потоков в группе, к которой принадлежит поток

public 
static int activeCount();

Текущему потоку разрешается изменять объект Thread

public 
void checkAccesss();

Определение количества фреймов в стеке

public int countStackFrames();

Определение текущего работающего потока

public static Thread currentThread();

Принудительное завершение работы потока

public 
void destroy();

Вывод текущего содержимого стека для отладки

public static 
void dumpStack();

Получение всех объектов Tread данной группы

public static 
int enumerate(Thread tarray[]);

Определение имени потока

public final String getName();

Определение текущего приоритета потока

public 
final int getPriority();

Определение группы, к которой принадлежит поток

public final 
ThreadGroup getThreadGroup();

Прерывание потока

public void interrupt();

Определение, является ли поток прерванным

public 
static boolean interrupted();

Определение, выполняется поток или нет

public final boolean isAlive();

Определение, является ли поток демоном

public 
final boolean isDaemon();

Определение, является ли поток прерванным

public boolean isInterrupted();

Ожидание завершения потока

public 
final void join();

Ожидание завершения потока в течение заданного времени. Время задается в миллисекундах

public 
final void join(long millis);

Ожидание завершения потока в течение заданного времени. Время задается в миллисекундах и наносекундах

public 
final void join(long millis, int nanos);

Запуск временно приостановленного потока

public final void 
resume();

Метод вызывается в том случае, если поток был создан как объект с интерфейсом Runnable

public 
void run();

Установка для потока режима демона

public final void setDaemon(boolean 
on);

Устаовка имени потока

public final void setName(String name);

Установка приоритета потока

public 
final void setPriority(int newPriority);

Задержка потока на заднное время. Время задается в миллисекундах и наносекундах

public 
static void sleep(long millis);

Задержка потока на заднное время. Время задается в миллисекундах и наносекундах

public 
static void sleep(long millis, int nanos);

Запуск потока на выполнение

public void start();

Остановка выполнения потока

public 
final void stop();

Аварийная остановка выполнения потока с заданным исключением

public final void stop(Throwable obj);

Приостановка потока

public 
final void suspend();

Строка, представляющая объект-поток

public String toString();

Приостановка текущего потока для того  чтобы управление было передано другому потоку

public 
static void yield  (); 
Создание дочернего класса на базе класса Thread

Рассмотрим первый способ реализации многопоточности, основанный на наследовании от класса Thread. При использовании этого способа вы определяете для потока отдельный класс, например, так:

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

Здесь определен класс DrawRectangles, который является дочерним по отношению к классу Thread.

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

Заметим, что метод run не вызывается напрямую никакими другими методами. Он получает управление при запуске потока методом start.

Как это происходит?

Рассмотрим процедуру запуска потока на примере некоторого класса DrawRectangles.

Вначале ваше приложение должно создать объект класса Thread:

public class MultiTask2 extends 
Applet { Thread m_DrawRectThread = null; . . . public void start() { if (m_DrawRectThread 
== null) { m_DrawRectThread = new DrawRectangles(this); m_DrawRectThread.start(); 
} } }

Создание объекта выполняется оператором new в методе start, который получает управление, когда пользователь открывает документ HTML с аплетом. Сразу после создания поток запускается на выполнение, для чего вызывается метод start.

Что касается метода run, то если поток используется для выполнения какой либо периодической работы, то этот метод содержит внутри себя бесконечный цикл. Когда цикл завершается и метод run возвращает управление, поток прекращает свою работу нормальным, не аварийным образом. Для аварийного завершения потока можно использовать метод interrupt.

Остановка работающего потока выполняется методом stop. Обычно остановка всех работающих потоков, созданных аплетом, выполняется методом stop класса аплета:

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

Напомним, что этот метод вызывается, когда пользователь покидает страницу сервера Web, содержащую аплет.

Реализация интерфейса Runnable

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

Идея заключается в том, что основной класс аплета, который является дочерним по отношению к классу Applet, дополнительно реализует интерфейс Runnable, как это показано ниже:

public class MultiTask extends 
Applet implements Runnable { Thread m_MultiTask = null; . . . public void run() 
{ . . . } public void start() { if (m_MultiTask == null) { m_MultiTask = new Thread(this); 
m_MultiTask.start(); } } public void stop() { if (m_MultiTask != null) { m_MultiTask.stop(); 
m_MultiTask = null; } } }

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

Для создания потока используется оператор new. Поток создается как объект класса Thread, причем конструктору передается ссылка на класс аплета:

m_MultiTask 
= new Thread(this);

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

Как запустить поток?

Запуск выполняется, как и раньше, методом start. Обычно поток запускается из метода start аплета, когда пользователь отображает страницу сервера Web, содержащую аплет. Остановка потока выполняется методом stop.

Назад Вперед

Начертательная геометрия и инженерная графика, перспектива