сокая скорость отклика на запросы пользователей. Поэтому нет
ничего удивительного в том, что в языке Java механизм потоков
представлен с самого начала и в полном об®еме.
В языке Java потоки представлены посредством класса Thread, ин-
терфейса ъunnable, спецификатора метода synchronized и методов
класса Object wait и notify.
4.1.6.1. Класс Thread и интерфейс ъunnable
Поток (thread) представляет собой отдельный поток управления в
пределах процесса. Таким образом, у каждого потока есть начало,
последовательность действий, текущее состояние и конец.
Поток запускается с помощью вызова метода start() класса
Thread. Последовательность действий, выполняемых в рамках пото-
ка, задается в методе run(). Подчеркнем, что метод run() ис-
пользуется только для задания помледовательности действий; явно
вызывать его не только не нужно, но и просто вредно.
Поток заканчивается либо при завершении выполнения метода
run(), либо с помощью явных вызовов методов класса Thread
stop() или destroy(). Возобновить работу завершенного потока
невозможно.
Для временной приостановки работы потока с последующим возоб-
новлением служат методы suspend(), sleep() и yeild().
Обычно поток, приостановленный с помощью метода suspend, возоб-
новляет работу посредством метода resume().
Вызов метода sleep() приводит к приостановке потока на заданное
число миллисекунд.
Вызов метода yeild() означает добровольную уступку процессора
другому потоку; первоначальный поток остается готовым к выпол-
нению.
Java-потоки обладают приоритетами. В спецификациях оговаривает-
ся, что Java-машина реализует вытесняющую многопотоковость. Это
означает, что поток с большим приоритетом может прервать выпол-
нение менее приоритетного потока. Однако, спецификации не тре-
буют наличия разделения времени. Это значит, что для передачи
управления потоку с тем же приоритетом, вообще говоря, требуют-
ся явные действия со стороны первоначального потока - вызов ме-
тодов suspend(), sleep() или yeild().
На рис. 10 представлена диаграмма состояний потоков.
Рис. 10. Диаграмма состояний потоков.
Следующий пример содержит фрагмент одного из многочисленных ва-
риантов решения задачи "производитель/потребитель". Он заимст-
вован из письма, которое написал Mark Tillotson в группу сете-
вых новостей comp.lang.java.
class my_producer extends Thread
{
int items_to_do ;
my_buffer the_buffer ;
my_producer (my_buffer buf, int count)
{ super() ;
the_buffer = buf ;
items_to_do = count ;
}
public void run ()
{
while (items_to_do > 0)
{ System.out.println ("producer to_do = " + items_to_do) ;
Integer item = new Integer (items_to_do*items_to_do) ;
the_buffer.insert (item) ;
items_to_do-- ;
}
System.out.println ("producer exiting") ;
}
}
Данный производитель помещает в буфер квадраты целых чисел.
В приведенном простом примере класс my_producer является нас-
ледником класса Thread, что делает его потоком с последователь-
ностью действий, заданной методом run(). В реальных программах,
как правило, об®ект должен наследовать у какого-либо предшест-
венника содержательные свойства, а возможность паралелльного
выполнения ему предоставляется интерфейсом ъunnable. Этот ин-
терфейс содержит единственный метод - run(). Пример.
1 class SomethingToъun extends Baseъunner implements ъunnable {
2 private Thread aThread;
3 public void run () {
// выполняемые действия
. . .
4 }
5 SomethingToъun () {
6 aThread = new Thread (this);
7 aTread.start ();
8 }
9 }
В строке 6 создается новый поток. Аргументом конструктора явля-
ется обект класса SomethingToъun, а, значит, последовательность
выполняемых действий потока будет определяться методом run()
этого класса. Вызов метода start() в строке 7 ставит поток в
очередь готовых для выполнения.
4.1.6.2. Средства синхронизации потоков
Как и во всякой многопроцессной или многопотоковой среде, в
Java существует проблема синхронизации доступа к разделяемым
ресурсам. Примером такого ресурса является буфер в задаче "про-
изводитель/потребитель".
Для опытных программистов отметим, что модель синхронизации,
принятая в языке Java, опирается на концепцию монитора, предло-
женную в 70-е годы Бринк-Хансеном.
В Java-программах можно выделять критические интервалы, которые
обозначаются ключевым словом synchronized. Если критическим ин-
тервалом является метод, спецификатор synchronized помещается в
его (метода) заголовок. Для превращения произвольной инструкции
(обычно это блок) в критический интервал служит конструкция
synchronized (выражение) инструкция;
где результатом выражения должен быть об®ект или массив.
Читать дальше