Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
89
Добавлен:
24.02.2016
Размер:
202.75 Кб
Скачать

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

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

Есть две возможности использования класса Thread.

Во-первых,можно создать собственный класс на базе класса Thread. При этом необходимо переопределить метод run(). Новая реализация этого метода будет работать в рамках отдельного потока.

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

Рассмотрим подробнее обе возможности реализации многозадачности.

Создание подкласса Thread

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

class myThread extends Thread

{ // этот метод получает управление при запуске

// потока методом start() класса Thread

public void run()

{ // здесь можно добавить код, который будет

// выполняться в рамках отдельного потока

}

// здесь можно добавить специализированный для класса код

}

Следует обратить внимание на метод run(). Этот метод должен быть всегда переопределен в классе, наследованном от Thread. Именно он определяет действия, выполняемые в рамках отдельного потока. Если поток используется для выполнения циклической работы, этот метод содержит внутри себя бесконечный цикл.

Метод run() не вызывается напрямую никакими другими методами. Он получает управление при запуске потока методом start() класса Thread.В случае апплетов создание и запуск потоков обычно осуществляется в методе start() апплета.

Остановка работающего потока раньше выполняелась методом stop()класса Thread.Обычно остановка всех работающих потоков, созданных апплетом, выполняется в методе stop() апплета. Сейчас использование этого метода является устаревшим и не рекомендуется. Завершение работы потока желательно проводить так, чтобы происходило естественное завершение методаrun. Для этого используется управляющая переменная в потоке. В наших потоках это переменная булевского типа –going.

Рассмотрим процедуру создания и запуска потоков на примере использования их в апплетах (в обычных приложениях потоки используются аналогично)- пример 1. Определим класс апплетовMultiTask:

/*------------- Пример 1. Файл MultiTask.java -------------*/

import java.applet.*;

import java.awt.*;

public class MultiTask extends Applet

{ public MultiTask()

{ // здесь можно добавить код конструктора

}

public String getAppletInfo()

{ return "Name: Applet\r\n"; // информация об апплете

}

public void init()

{ resize(320, 240); // установка размера апплета

// здесь можно добавить код инициализации апплета

}

public void destroy()

{ // здесь можно добавить код завершения работы апплета

}

public void paint(Graphics g)

{ // здесь можно добавить код вывода в окно апплета

}

public void start()

{ // здесь можно добавить код, работающий при запуске апплета

}

public void stop()

{ // здесь можно добавить код, работающий при остановке

}

// здесь можно добавить специализированный для класса код

}

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

// поток, рисующий прямоугольники в окне апплета

class DrawRects extends Thread

{ // конструктор, получающий ссылку на создателя объекта - апплет

boolean going = 1;

public DrawRects(MultiTask parentObj)

{ parent=parentObj;

}

public void run()

{ Graphics gr=parent.getGraphics(); // контекст апплета

while(going) // в цикле выводятся прямоугольники

{ int w=parent.size().width-1, h=parent.size().height-1;

gr.setColor(new Color((float)Math.random(),

(float)Math.random(),(float)Math.random()));

gr.fillRect((int)(Math.random()*w),(int)(Math.random()*h),

(int)(Math.random()*w),(int)(Math.random()*h));

}

}

MultiTask parent; // ссылка на создателя объекта

}

// поток, рисующий эллипсы в окне апплета

class DrawOvals extends Thread

{ // конструктор, получающий ссылку на создателя объекта - апплет

boolean going = 1;

public DrawOvals(MultiTask parentObj)

{ parent=parentObj;

}

public void run()

{ Graphics gr=parent.getGraphics(); // контекст апплета

while(going) // в цикле выводятся эллипсы

{ int w=parent.size().width-1, h=parent.size().height-1;

gr.setColor(new Color((float)Math.random(),

(float)Math.random(),(float)Math.random()));

gr.fillOval((int)(Math.random()*w),(int)(Math.random()*h),

(int)(Math.random()*w),(int)(Math.random()*h));

}

}

MultiTask parent; // ссылка на создателя объекта

}

Теперь рассмотрим процесс использования созданных классов. Вначале апплет должен объявить в качестве своих элементов ссылки на объекты классов потоков:

DrawRects Rects =null;

DrawOvals Ovals =null;

Далее в методе start() апплета создаются объекты потоков и потоки запускаются на выполнение:

public void start()

{ if(Rects==null) { Rects=new DrawRects(this); Rects.start(); }

if(Ovals==null) { Ovals=new DrawOvals(this); Ovals.start(); }

}

Когда пользователь покидает страницу апплета, то вызывается метод stop() апплета. Именно в этом методе целесообразно останавливать работающие потоки:

public void stop()

{ if(Rects!=null) Rects.going=0; if(Ovals!=null) Ovals.going=0;

}