Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Теория экзамен.doc
Скачиваний:
25
Добавлен:
29.05.2015
Размер:
516.61 Кб
Скачать

Создание потоков

Создатели Java милостиво предоставили две возможности создания потоков: реализовать(implementing) интерфейс и расширить(extending) класс. Расширение класса это путь наследования методов и переменных класса родителя. В этом случае можно наследоваться только от одного родительского класса. Это ограничение внутри Java можно побороть реализацией интерфейса, который является наиболее распространённым способом создания потоков. (Заметим, что способ наследования позволяет только запустить класс как поток. Это позволяет классу только выполнить start() и т.п.).

Интерфейсы дают возможность программистам заложить фундамент одного класса. Они используются для разработки требований к набору классов для реализации. Интерфейс устанавливает правила. Разные наборы классов, которые реализуют интерфейс, должны следовать этим правилам.

Есть некоторые отличия между классом и интерфейсом. Во-первых, интерфейс может только содержать абстрактные методы и/или static final переменные (константы). Классы, с другой стороны, могут реализовывать методы и содержать переменные, которые не выступают в качестве констант. Во-вторых, интерфейс не может реализовывать никаких методов. Класс, который реализовывает интерфейс, должен реализовать все методы, которые описаны в интерфейсе. У интерфейса есть возможность расширяться за счёт других интерфейсов, и (в отличие от классов) могут расширяться от нескольких интерфейсов. К тому же, экземпляр интерфейса не может быть создан, используя, оператор new; например, Runnable a = new Runnable(); не разрешается.

Для первого способа создания потока необходимо просто наследоваться от класса Thread. Делайте так, только если классу нужно только выполниться как отдельному потоку и никогда не понадобиться наследоваться от другого класса. Класс Thread определён в пакете java.lang, который необходимо импортировать, что бы наши классы знали о его описании:

import java.lang.*; public class Counter extends Thread { public void run() { .... } }

Пример выше создаёт новый класс Counter, который расширяет класс Thread и подменяет метод Thread.run() для своей реализации. В методе run() происходит вся работа класса Counter как потока. Такой же класс можно создать, реализуя интерфейс Runnable:

import java.lang.*; public class Counter implements Runnable { Thread T; public void run() { .... } }

Здесь осуществляется абстрактный метод run(), который описан в интерфейсе Runnable. Отметим, что у нас есть экземпляр класса Thread, переменная класса Counter. Единственное отличие этих двух методов заключается в том, что реализация Runnable является более гибкой для создания класса Counter. В примере, который описан выше, есть возможность расширения класса Counter, если в этом есть такая необходимость. Большинство классов, которые должны выполняться как потоки, реализуют Runnable, поскольку они, вероятно, могут расширить свою функциональность за счёт другого класса.

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

package java.lang; public interface Runnable { public abstract void run(); }

Это и всё, что есть в интерфейсе Runnable. Интерфейс – это всего лишь описание, которое классы должны реализовать. Итак, Runnable, заставляет только запустить метод run(). Вследствие этого, большая часть работы полагается на класс Thread. Более пристальный взгляд на класс Thread даст представление о том, что на самом деле происходит:

public class Thread implements Runnable { ... public void run() { if (target != null) { target.run(); } } ... }

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