Владимир Цишевский - Java как центр архипелага
- Название:Java как центр архипелага
- Автор:
- Жанр:
- Издательство:неизвестно
- Год:1996
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Владимир Цишевский - Java как центр архипелага краткое содержание
Java как центр архипелага - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
риантов решения задачи "производитель/потребитель". Он заимст-
вован из письма, которое написал 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 (выражение) инструкция;
где результатом выражения должен быть об®ект или массив.
Выполнение критического интервала начинается только после полу-
чения потоком монопольного доступа к соответствующему об®екту.
До наступления этого момента поток блокируется.
Вызов wait() внутри критического интервала приводит к тому, что
текущий поток уступает монопольное право на критический интер-
вал и приостанавливается до тех пор, пока из какого-либо друго-
го потока не будет сделан вызов notify() или notifyAll(). Хоро-
шей иллюстрацией использования средств синхронизации потоков
является упоминавшаяся выше программа Марка Тиллотсона.
class my_buffer
{
Object [] vec = new Object [8] ;
int ip = 0 ;
int ep = 0 ;
synchronized void insert (Object item)
{
do
{
if (ip-ep < 8)
{ vec [(ip++) & 7] = item ;
if (ip-ep == 1) notify () ; // Уведомить, если буфер был пуст
return ;
}
try wait () ; catch (InterruptedException e) ;
} while (true) ;
}
synchronized Object extract ()
{
do
{
if (ip > ep)
{ Object result = vec [(ep++) & 7] ;
if (ip-ep == 7) notify(); // Уведомить, если буфер был полон
return result ;
}
try wait () ; catch (InterruptedException e) ;
} while (true) ;
}
}
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 ("Производитель заканчивает работу") ;
}
}
class my_consumer extends Thread
{
int items_to_do ;
my_buffer the_buffer ;
my_consumer (my_buffer buf, int count)
{ super() ;
the_buffer = buf ;
items_to_do = count ;
}
public void run ()
{
while (items_to_do > 0)
{ System.out.println ("consumer to_do = " + items_to_do) ;
Object item = the_buffer.extract () ;
System.out.println ("consumer got " + item) ;
items_to_do-- ;
}
System.out.println ("Потребитель заканчивает работу") ;
synchronized (this){
notify () ; // Посылаем уведомление о завершении работы
// (см. con.wait() в main())
}
}
}
public class threaded3
{
public static void main (String [] args) throws InterruptedException
{
my_buffer the_buffer = new my_buffer () ;
my_producer prod = new my_producer (the_buffer, 40) ;
my_consumer con = new my_consumer (the_buffer, 40) ;
Thread.currentThread().setPriority (5) ;
prod.setPriority (4) ; // Производитель получает более высокий приоритет
con.setPriority (3) ; // по сравнению с потребителем
prod.start() ;
con.start() ;
synchronized (con)
{
con.wait() ; // Ждем уведомления от производителя об окончании
// его работы
}
System.out.println ("Производитель и потребитель закончили работу") ;
}
}
Приведенная программа написана в очень хорошем, понятном стиле.
Мы прокомментируем лишь один момент. В методах insert() и
extract() класса my_buffer вызов wait() содержится внутри бес-
конечного цикла. Дело в том, что вызов notify() относится к об-
®екту в целом. "Разбуженный" об®ект должен проанализировать
свое состояние и решить, что делать дальше. Так, если "заснул"
метод insert(), то после возобновления работы необходимо прове-
рить, что буфер уже не полон и добавление нового элемента стало
возможным. Если это не так, метод insert() заснет вновь.
* 4.2. Технология Java
4.2.1. Технологический цикл обработки Java-программ
В принципе, технологический цикл подготовки, трансляции, редак-
тирования внешних связей, тестирования, отладки и выполнения
Java-программ тот же, что и для других интерпретируемых языков
программирования, но с одним существенным отличием - при редак-
тировании внешних связей требуемые компоненты могут доставлять-
ся по сети (рис. xxx).
Рис. xxx. Технологический цикл Java-программы
Важно отметить, однако, что Java-программы могут представать
как бы в двух ипостасях - как самостоятельное приложение и как
аплет, то есть совокупность об®ектов, выполняющихся в среде
WWW-навигатора.
С точки зрения программиста, аплет и приложение отличаются в
первую очередь точками входа и жизненным циклом.
Приложение в качестве точки входа имеет метод
public static void main (String args[]);
этот метод должен быть определен в том public-классе, который содержится в
файле, выполняемом виртуальной Java-машиной.
В параметр args передается массив строк - параметров командной строки.
Пример: программа, печатающая свои аргументы
public class myTop {
public static void main (String args[]){
int argc = args.length;
for (int i = 0; i < argc; i++)
System.out.println (argc[i]);
}
}
Аплет выполняется в контексте навигатора и его жизненный цикл
определяется следующими методами класса Applet:
public void init () вызывается навигатором при загрузка аплета;
public void start (); вызывается навигатором при показе страницы;
public void stop (); вызывается навигатором, когда тот уходит с Web-страницы;
public void destroy (); этот метод предназначен для освобожденя
Читать дальшеИнтервал:
Закладка: