public class GenDemo extends Applet
{
Gen<Integer> iOb;
Gen<String> strOb;
public void init()
{
int i=Integer. parseInt(getParameter("intParam"));
iOb=new Gen<Integer>(i);
String s=getParameter("strParam");
strOb=new Gen<String>(s);
}
public void paint(Graphics g)
{
iOb. showType(g, 10,10);
strOb. showType(g, 30,10);
}
class Gen<T>
{
// объявление настраиваемого класса Gen
...
}
}
Итак, в апплет передается два параметра. Один из них – целое число, другой – символьная строка. Для хранения этих данных в классе GenDemo объявляются ссылки на объекты типов Gen<Integer> и Gen<String>. Типы данных Integer и String в данном случае являются параметрами настраиваемых типов. При создании первой ссылки параметру T класса Gen присваивается значение Integer. Это значит, что генерируется реализация класса Gen для работы с целыми числами и iOb является объектом именно этого класса. Во втором случае аналогичная работа проводится со значением типа String и объектом strOb. Далее при работе с объектом iOb везде, где упоминался тип Т в классе Gen используется тип Integer, а при работе с объектом strOb тип Т становится типом String.
При создании настраиваемых классов требуется иметь в виду следующее правило. При объявлении объекта настраиваемого типа данных аргумент типа, передаваемый классу как параметр, должен быть каким-либо классом. Использование в качестве аргумента типа стандартных типов данных, например, int или char, не разрешается. Если же возникнет такая необходимость, требуется использовать класс-оболочку, соответствующий нужному стандартному типу данных.
Приложение 4. Работа с JDK в режиме командной строки
Бывают ситуации, когда с пакетом JDK приходится работать непосредственно из командной строки, минуя какие-либо графические оболочки. Для этого операционную систему необходимо предварительно настроить. Эта настройка производится один раз. Рассмотрим правила настройки для самой распространенной в настоящее время операционной системы – Windows XP.
Операционная система должна иметь информацию, какой каталог JDK содержит программы, нужные для компиляции и запуска апплетов и приложений. Поэтому следует настроить переменную среды Path. Для этого выполните следующие действия.
· Выберите "Пуск" – "Панель управления" – "Администрирование" – "Управление компьютером" и в левой части окна щелкните правой кнопкой мыши по строке "Управление компьютером".
· В появившемся контекстном меню выберите пункт "Свойства", затем в окне свойств перейдите на закладку "Дополнительно".
· В группе "Переменные среды" нажмите на кнопку "Параметры".
· В списке "Системные переменные" выберите переменную Path и нажмите на кнопку "Изменить".
· В текстовом поле "Значение переменной" добавьте точку с запятой и полное имя каталога BIN пакета JDK. Например, если JDK установлен в каталог D:\jdk1.4, то это имя будет выглядеть как D:\jdk1.4\bin. Соответственно, если переменной Path в списке не было, тогда ее требуется создать, и в этом случае точку с запятой в значении переменной указывать не надо.
Теперь можно работать с командной строкой. Выберите "Пуск" – "Выполнить", наберите и выполните команду cmd. Появится черное окно командной строки – окно DOS, в котором указывается строка приглашения в виде имени текущего каталога. В этом окне можно выполнять команды только в текстовом режиме. Для вывода списка стандартных команд наберите help и нажмите Enter. Чаще всего приходится использовать команды перемещения по каталогам, например:
d: – переход к диску D;
cd .. – переход к родительскому каталогу;
cd MyJava – переход к подкаталогу MyJava текущего каталога (относительная ссылка);
cd d:\MyJava – переход к подкаталогу MyJava диска D (абсолютная ссылка).
По списку ранее введенных команд можно перемещаться стрелками вверх-вниз.
Теперь перейдем к работе с JDK. Предположим, мы хотим откомпилировать какой-то апплет. Сначала следует перейти в каталог, в котором находится java-файл этого апплета. Для компиляции используется программа javac:
javac FirstApplet. java
Если в программе были ошибки, они будут выведены в окно, если же ошибок не было, то в окне снова появится строка приглашения. Обратите внимание, что расширение файла.java указывать обязательно.
Теперь мы хотим просмотреть результат работы апплета. Для этого служит команда appletviewer.
appletviewer FirstApplet. html
Обратите внимание, что в качестве параметра в этой команде указывается html-файл. После выполнения этой команды будет выведено отдельное окно с запущенным апплетом (Kawa использует то же самое окно для запуска апплетов).
Для компиляции приложений используется та же команда javac, что и для апплетов, например,
javac ChatServer. java
А запуск приложений выглядит несколько по-другому. Для этого служит команда java. Например:
java ChatServer
Регистр символов в названии класса является существенным! Запустите эту команду на выполнение. Вы получите сообщение:
Exception in thread "main"
java. lang. NoClassDefFoundError: ChatServer
Данное сообщение означает, что java-машина не находит файл ChatServer.class, хотя он и находится в текущем каталоге. Для исправления этой ошибки следует вернуться к настройке переменных среды и создать переменную Classpath. Эта переменная указывает, где java-машина должна искать нестандартные классы. В качестве значения переменной укажите символ "." – это соответствует текущему каталогу.
Таким же образом подключаются и другие нестандартные классы, например, пакет для работы с mysql. Пусть он называется mysql-connector-java-3.0.8-stable-bin. jar и находится в каталоге C:\mysql. Для использования этого пакета в значение переменной Classpath через точку с запятой добавьте строку C:\mysql\mysql-connector-java-3.0.8-stable-bin. jar.
Обратите внимание, что при работе с окном командной строки русские символы выводятся в кодировке DOS, поэтому, например, кодировка Win1251 в этом окне будет нечитаемой.
Приложение 5. Коды примеров
Пример 1. Приложение, использующее потоки.
class WalkmanHire {
/* Прокат плееров-экскурсоводов J M Bishop Январь 1997
* Программа имитирует прокат плееров для посетителей музея.
* Имеется некоторое фиксированное количество плееров и не-
* сколько служащих, которые их выдают посетителям под денежный
* залог и принимают обратно с возвратом залога.
* По умолчанию имеется 50 плееров и 3 сотрудника. Эти значения
* можно изменить, если запустить программу с параметрами, на-
* пример,
* java WalkmanHire 100 8.
* Изначально сумма полученного залога равна 0.
* Иллюстрируют применение синхронизации, а также
* использование методов wait и notify.
* В программе одновременно используются потоки двух разных
* типов – класс мГруппа посетитителей" и класс "Сотрудник"
*/
public static void main (String [] args) {
// получение числа плееров, начало имитации
// деятельности музея
if (args. length >= 1)
pool = Integer. parseInt(args[0]);
else pool = 50;
Museum m = new Museum (pool);
// получение количества сотрудников,
// создание и запуск потоков для имитации работы сотрудников
if (args. length >= 2)
helpers = Integer. parseInt(args[1]);
else helpers = 3;
for (int i=0; i<helpers; i++)
new Counter (m, i).start();
}
static int pool;
static int helpers;
}
import java. io.*;
class Museum {
Museum (int w) {
walkmen = w;
cash = 0;
}
synchronized void hire (int c, int n) {
// Если недостаточно свободных плееров,
// ждать, пока не будет произведен возврат количества,
// необходимого для текущей группы посетителей
System. out. println("Сотруднику "+c+" требуется "+n+
" плееров");
while (walkmen < n) {
try { wait(); }
catch (InterruptedException e) {}
}
// Выдать плееры и принять залог.
// Пробудить следующий поток, находящийся в состоянии
// ожидания.
walkmen -= n;
cash += n;
System. out. println("Сотрудник "+c+" выдал "+n+" плееров");
System. out. println("Текущее состояние:"+
" Залог: "+cash+" Всего: "+(walkmen+cash)
+ " Плееры в наличии: "+walkmen);
notify ();
}
synchronized void replace (int n) {
// Принять плееры, вернуть залог и пробудить следующий
// поток, находящийся в состоянии ожидания
System. out. println("Возвращено "+n+" плееров");
walkmen +=n;
cash -= n;
notify ();
}
private static int walkmen;
private static int cash;
}
class Visitors extends Thread {
Visitors (Museum m, int w) {
museum = m;
groupSize = w;
}
public void run () {
// Группа осматривает экспозицию музея в течение случайного
// интервала времени (от 1 до 2 секунд), затем возвращает
// плееры и покидает музей.
// Поток "Группа посетителей" уничтожается.
try {sleep((int) (Math. random()*1000)+1);} catch(InterruptedException e) {}
museum. replace(groupSize);
}
Museum museum;
int groupSize;
}
class Counter extends Thread {
Counter (Museum m, int q) {
museum = m;
queue = q;
}
public void run () {
// Генерируется количество посетителей в новой группе,
// выдается нужное количество плееров,
// создается и запускается объект-поток
// для группы посетителей.
while (true) {
int w = a(7);
museum. hire(queue, w);
new Visitors (museum, w).start();
// Генерируется пауза перед приходом
// следующей группы посетителей
try {sleep(a(100));} catch(InterruptedException e) {}
}
}
Museum museum;
int queue;
static int a (int x) {
return (int) (Math. random() * x) +1;
}
}
Пример 2. Два потока, соединенные каналом ввода-вывода. Один поток рисует фейерверк, другой формирует для него цвет
/* Апплет, иллюстрирующий обмен данными с помощью каналов ввода-
* вывода. Апплет производит рисование залпов фейерверка.
* Рисованием фейерверка занимается объект-поток типа
* ZalpThr. Другой поток (типа ColorThr) случайным образом
* генерирует цвет очередной серии залпов.
* Для передачи сгенерированного цвета в объект-поток рисования
* фейерверка используются канальные потоки ввода-вывода,
* которые создаются в объекте-апплете.
*/
import java. awt.*;
import java. applet.*;
import java. io.*;
// класс рисования фейерверка
public class Zalp extends Applet
{
// канальный поток ввода (для чтения сгенерированного цвета)
PipedInputStream in=null;
// канальный поток вывода (для передачи сгенерированного цвета)
PipedOutputStream out=null;
public void init()
{
// создание канальных потоков ввода-вывода
try
{
in = new PipedInputStream();
// поток вывода создается на основе потока ввода
// для организации коммуникационного канала
// между ними
out = new PipedOutputStream(in);
}
catch(IOException ex)
{
}
setBackground(Color. black);
// создание потока рисования фейерверка,
// в качестве параметров конструктора передаются
// поток ввода для получения цвета рисования и
// графический контекст апплета
new ZalpThr(in, getGraphics()).start();
// создание потока генерации цвета фейерверка,
// в качестве параметров конструктора передается
// поток вывода для передачи цвета
new ColorThr(out).start();
}
}
import java. io.*;
// поток генерации цвета фейерверка
class ColorThr extends Thread
{
PipedOutputStream out;
ColorThr(PipedOutputStream out)
{
this. out=out;
}
public void run()
{
while (true)
{
try
{
// генерация компонентов цвета и отправка
// их через канал вывода потоку рисования
// фейерверка
out. write(100+(int)(Math. random()*155));
out. write(100+(int)(Math. random()*155));
out. write(100+(int)(Math. random()*155));
}
catch(IOException ex)
{
}
try
{
// задается пауза до генерации
// следующего цвета
sleep((int)(Math. random()*10000));
}
catch(InterruptedException e)
{ }
}
}
}
import java. awt.*;
import java. io.*;
// класс рисования фейерверка
class ZalpThr extends Thread
{
int M=300,N=300;
int zx, zy;
int zd;
boolean znew=true;
int r, g,b;
PipedInputStream in=null;
Graphics gr;
ZalpThr(PipedInputStream in, Graphics gr)
{
this. in=in;
this. gr=gr;
}
public void run()
{
while (true)
{
if (znew)
{
zx=(int)(Math. random()*M);
zy=(int)(Math. random()*N);
zd=0;
znew=false;
// проверяем наличие данных в потоке ввода
// если они там есть, то считываем их
try
{
if (in. available()>0)
r=in. read();
if (in. available()>0)
g=in. read();
if (in. available()>0)
b=in. read();
}
catch(IOException ex)
{
System. out. println("Exception!!!");
}
}
else
{
zd+=10;
if(zd>=M)
znew=true;
}
paint();
try
{
sleep(50);
}
catch(InterruptedException e)
{
}
}
}
public void paint()
{
int x, y;
int d;
Color col=new Color(r, g,b);
gr. setColor(col);
gr. clearRect(0,0,M, N);
if (zd==0)
{
gr. fillOval(zx, zy,10,10);
}
else if (zd<=M/2)
{
double dvaPI=2*Math. PI;
double step=dvaPI/100;
for (double i=0; i<dvaPI; i+=step)
{
d=zd/2+(int)(Math. random()*zd/2);
x=zx+(int)(d*Math. cos(i));
y=zy-(int)(d*Math. sin(i));
gr. fillOval(x, y,5,5);
}
}
}
}
Пример 3. Чат-сервер
/* Чат-сервер J M Bishop Январь 1997
* Модифицированная версия - Java 1.1 Январь 1998
* Создает сервер для обмена сообщениями.
*
* Подключение клиента:
* telnet x y
* где x и y - имя и порт компьютера,
* на котором запущен сервер.
*
* Иллюстрирует сокеты, ввод-вывод на сокетах
* потоки, синхронизацию и использование списков.
*/
import java. io.*;
import .*;
public class ChatServer {
private static List clientList = new List();
private static int id = 0;
public static void main(String[] args) throws IOException {
// Назначаем порт и создаем сокет.
int port = 8190;
if (args. length > 0)
port = Integer. parseInt(args[0]);
ServerSocket listener = new ServerSocket(port);
System. out. println("The Chat Server is running " +
" on port "+port);
// Ожидаем (слушаем) новых клиентов.
// Для каждого клиента создаем поток-обработчик.
// Добавляем клиента в связный список.
while (true) {
Socket client = listener. accept();
new ChatHandler(client).start();
System. out. println("New client no."+id+
" from "+ client. getInetAddress()+
" on client's port "+client. getPort());
clientList. reset();
clientList. add(client);
id++;
}
}
static synchronized void broadcast
(String message, String name)
throws IOException {
// Посылаем сообщение всем клиентам.
Socket s;
PrintWriter p;
for (clientList. reset();
!clientList. eol(); clientList. succ())
{
s = (Socket)clientList. current();
p = new PrintWriter(s. getOutputStream(), true);
p. println(name+": "+message);
}
}
static synchronized void remove(Socket s) {
// Ищем клиента в списке (по ссылке на его сокет)
// и удаляем его из списка.
Socket t;
for (clientList. reset();
!clientList. eol(); clientList. succ())
{
t = (Socket)clientList. current();
if (t. equals(s))
break;
}
clientList. remove();
id--;
}
}
class ChatHandler extends Thread {
// Класс ChatHandler вызывается из ChatServer:
// один поток для каждого клиента, подключившегося к чату.
private BufferedReader in;
private PrintWriter out;
private Socket toClient;
private String name;
ChatHandler(Socket s) {
toClient = s;
}
public void run() {
try {
// Создаем потоки ввода-вывода для сокета
// и печатаем приглашение.
in = new BufferedReader(new InputStreamReader(
toClient. getInputStream()));
out = new PrintWriter(toClient. getOutputStream(),
true);
out. println("*** Welcome to the Chatter ***");
out. println("Type BYE to end");
out. println("What is your name? ");
out. flush();
String name = in. readLine();
ChatServer. broadcast(name+
" has joined the discussion.", "Chatter");
// Читаем строки сообщения
// и отправляем сообщение всем клиентам.
while (true) {
String s = in. readLine().trim();
// Проверяем первые три символа для BYE.
// Избегаем проблем с разными символами конца строки.
if (s. length() > 2 && s. charAt(0) == 'B' &&
s. charAt(1) == 'Y' && s. charAt(2) == 'E') {
ChatServer. broadcast(name+
" has left the discussion.","Chatter");
break;
}
ChatServer. broadcast(s, name);
}
ChatServer. remove(toClient);
toClient. close();
} catch (Exception e) {
System. out. println("Chatter error: "+e);
}
}
}
class List {
// Класс Список, J M Bishop Октябрь 1997
// Поддерживает список объектов
// в порядке LIFO (Last-in-First-out),
// содержит метод-итератор.
private Node start, now, prev;
public List() {
now = null;
start = null;
prev = null;
}
public void add(Object x) {
if (start == null) {
start = new Node(x, null);
now = start;
} else {
Node T = new Node(x, now. link);
now. link = T;
prev = now;
now = T;
}
}
public void remove() {
if (isempty() || eol()) {
return;
} else {
if (prev == null) {
start = now. link;
} else {
prev. link = now. link;
now = now. link;
}
}
}
public boolean isempty() {
return start == null;
}
public Object current() {
return now. data;
}
public void reset() {
now = start;
prev = null;
}
public boolean eol() {
return now == null;
}
public void succ() {
now = now. link;
if (prev == null)
prev = start;
else
prev = prev. link;
}
class Node {
// Класс Node для хранения объектов,
// которые связаны в список.
Node link;
Object data;
Node(Object d, Node n) {
link = n;
data = d;
}
}
}
Пример 4. HTML-форма, передающая параметры сервлету. Данная форма предназначена для ввода и отсылки данных при оформлении заказа в электронном магазине.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>Оформление заказа</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<H1 ALIGN="CENTER">Оформление заказа</H1>
<FORM ACTION="/servlet/ShowParameters" METHOD="POST">
Код товара: <INPUT TYPE="TEXT" NAME="itemNum"><BR>
Количество: <INPUT TYPE="TEXT" NAME="quantity"><BR>
Цена за штуку: <INPUT TYPE="TEXT" NAME="price" VALUE="
public class GenDemo extends Applet
{
Gen<Integer> iOb;
Gen<String> strOb;
public void init()
{
int i=Integer. parseInt(getParameter("intParam"));
iOb=new Gen<Integer>(i);
String s=getParameter("strParam");
strOb=new Gen<String>(s);
}
public void paint(Graphics g)
{
iOb. showType(g, 10,10);
strOb. showType(g, 30,10);
}
class Gen<T>
{
// объявление настраиваемого класса Gen
...
}
}
Итак, в апплет передается два параметра. Один из них – целое число, другой – символьная строка. Для хранения этих данных в классе GenDemo объявляются ссылки на объекты типов Gen<Integer> и Gen<String>. Типы данных Integer и String в данном случае являются параметрами настраиваемых типов. При создании первой ссылки параметру T класса Gen присваивается значение Integer. Это значит, что генерируется реализация класса Gen для работы с целыми числами и iOb является объектом именно этого класса. Во втором случае аналогичная работа проводится со значением типа String и объектом strOb. Далее при работе с объектом iOb везде, где упоминался тип Т в классе Gen используется тип Integer, а при работе с объектом strOb тип Т становится типом String.
При создании настраиваемых классов требуется иметь в виду следующее правило. При объявлении объекта настраиваемого типа данных аргумент типа, передаваемый классу как параметр, должен быть каким-либо классом. Использование в качестве аргумента типа стандартных типов данных, например, int или char, не разрешается. Если же возникнет такая необходимость, требуется использовать класс-оболочку, соответствующий нужному стандартному типу данных.
Приложение 4. Работа с JDK в режиме командной строки
Бывают ситуации, когда с пакетом JDK приходится работать непосредственно из командной строки, минуя какие-либо графические оболочки. Для этого операционную систему необходимо предварительно настроить. Эта настройка производится один раз. Рассмотрим правила настройки для самой распространенной в настоящее время операционной системы – Windows XP.
Операционная система должна иметь информацию, какой каталог JDK содержит программы, нужные для компиляции и запуска апплетов и приложений. Поэтому следует настроить переменную среды Path. Для этого выполните следующие действия.
· Выберите "Пуск" – "Панель управления" – "Администрирование" – "Управление компьютером" и в левой части окна щелкните правой кнопкой мыши по строке "Управление компьютером".
· В появившемся контекстном меню выберите пункт "Свойства", затем в окне свойств перейдите на закладку "Дополнительно".
· В группе "Переменные среды" нажмите на кнопку "Параметры".
· В списке "Системные переменные" выберите переменную Path и нажмите на кнопку "Изменить".
· В текстовом поле "Значение переменной" добавьте точку с запятой и полное имя каталога BIN пакета JDK. Например, если JDK установлен в каталог D:\jdk1.4, то это имя будет выглядеть как D:\jdk1.4\bin. Соответственно, если переменной Path в списке не было, тогда ее требуется создать, и в этом случае точку с запятой в значении переменной указывать не надо.
Теперь можно работать с командной строкой. Выберите "Пуск" – "Выполнить", наберите и выполните команду cmd. Появится черное окно командной строки – окно DOS, в котором указывается строка приглашения в виде имени текущего каталога. В этом окне можно выполнять команды только в текстовом режиме. Для вывода списка стандартных команд наберите help и нажмите Enter. Чаще всего приходится использовать команды перемещения по каталогам, например:
d: – переход к диску D;
cd .. – переход к родительскому каталогу;
cd MyJava – переход к подкаталогу MyJava текущего каталога (относительная ссылка);
cd d:\MyJava – переход к подкаталогу MyJava диска D (абсолютная ссылка).
По списку ранее введенных команд можно перемещаться стрелками вверх-вниз.
Теперь перейдем к работе с JDK. Предположим, мы хотим откомпилировать какой-то апплет. Сначала следует перейти в каталог, в котором находится java-файл этого апплета. Для компиляции используется программа javac:
javac FirstApplet. java
Если в программе были ошибки, они будут выведены в окно, если же ошибок не было, то в окне снова появится строка приглашения. Обратите внимание, что расширение файла.java указывать обязательно.
Теперь мы хотим просмотреть результат работы апплета. Для этого служит команда appletviewer.
appletviewer FirstApplet. html
Обратите внимание, что в качестве параметра в этой команде указывается html-файл. После выполнения этой команды будет выведено отдельное окно с запущенным апплетом (Kawa использует то же самое окно для запуска апплетов).
Для компиляции приложений используется та же команда javac, что и для апплетов, например,
javac ChatServer. java
А запуск приложений выглядит несколько по-другому. Для этого служит команда java. Например:
java ChatServer
Регистр символов в названии класса является существенным! Запустите эту команду на выполнение. Вы получите сообщение:
Exception in thread "main"
java. lang. NoClassDefFoundError: ChatServer
Данное сообщение означает, что java-машина не находит файл ChatServer.class, хотя он и находится в текущем каталоге. Для исправления этой ошибки следует вернуться к настройке переменных среды и создать переменную Classpath. Эта переменная указывает, где java-машина должна искать нестандартные классы. В качестве значения переменной укажите символ "." – это соответствует текущему каталогу.
Таким же образом подключаются и другие нестандартные классы, например, пакет для работы с mysql. Пусть он называется mysql-connector-java-3.0.8-stable-bin. jar и находится в каталоге C:\mysql. Для использования этого пакета в значение переменной Classpath через точку с запятой добавьте строку C:\mysql\mysql-connector-java-3.0.8-stable-bin. jar.
Обратите внимание, что при работе с окном командной строки русские символы выводятся в кодировке DOS, поэтому, например, кодировка Win1251 в этом окне будет нечитаемой.
Приложение 5. Коды примеров
Пример 1. Приложение, использующее потоки.
class WalkmanHire {
/* Прокат плееров-экскурсоводов J M Bishop Январь 1997
* Программа имитирует прокат плееров для посетителей музея.
* Имеется некоторое фиксированное количество плееров и не-
* сколько служащих, которые их выдают посетителям под денежный
* залог и принимают обратно с возвратом залога.
* По умолчанию имеется 50 плееров и 3 сотрудника. Эти значения
* можно изменить, если запустить программу с параметрами, на-
* пример,
* java WalkmanHire 100 8.
* Изначально сумма полученного залога равна 0.
* Иллюстрируют применение синхронизации, а также
* использование методов wait и notify.
* В программе одновременно используются потоки двух разных
* типов – класс мГруппа посетитителей" и класс "Сотрудник"
*/
public static void main (String [] args) {
// получение числа плееров, начало имитации
// деятельности музея
if (args. length >= 1)
pool = Integer. parseInt(args[0]);
else pool = 50;
Museum m = new Museum (pool);
// получение количества сотрудников,
// создание и запуск потоков для имитации работы сотрудников
if (args. length >= 2)
helpers = Integer. parseInt(args[1]);
else helpers = 3;
for (int i=0; i<helpers; i++)
new Counter (m, i).start();
}
static int pool;
static int helpers;
}
import java. io.*;
class Museum {
Museum (int w) {
walkmen = w;
cash = 0;
}
synchronized void hire (int c, int n) {
// Если недостаточно свободных плееров,
// ждать, пока не будет произведен возврат количества,
// необходимого для текущей группы посетителей
System. out. println("Сотруднику "+c+" требуется "+n+
" плееров");
while (walkmen < n) {
try { wait(); }
catch (InterruptedException e) {}
}
// Выдать плееры и принять залог.
// Пробудить следующий поток, находящийся в состоянии
// ожидания.
walkmen -= n;
cash += n;
System. out. println("Сотрудник "+c+" выдал "+n+" плееров");
System. out. println("Текущее состояние:"+
" Залог: "+cash+" Всего: "+(walkmen+cash)
+ " Плееры в наличии: "+walkmen);
notify ();
}
synchronized void replace (int n) {
// Принять плееры, вернуть залог и пробудить следующий
// поток, находящийся в состоянии ожидания
System. out. println("Возвращено "+n+" плееров");
walkmen +=n;
cash -= n;
notify ();
}
private static int walkmen;
private static int cash;
}
class Visitors extends Thread {
Visitors (Museum m, int w) {
museum = m;
groupSize = w;
}
public void run () {
// Группа осматривает экспозицию музея в течение случайного
// интервала времени (от 1 до 2 секунд), затем возвращает
// плееры и покидает музей.
// Поток "Группа посетителей" уничтожается.
try {sleep((int) (Math. random()*1000)+1);} catch(InterruptedException e) {}
museum. replace(groupSize);
}
Museum museum;
int groupSize;
}
class Counter extends Thread {
Counter (Museum m, int q) {
museum = m;
queue = q;
}
public void run () {
// Генерируется количество посетителей в новой группе,
// выдается нужное количество плееров,
// создается и запускается объект-поток
// для группы посетителей.
while (true) {
int w = a(7);
museum. hire(queue, w);
new Visitors (museum, w).start();
// Генерируется пауза перед приходом
// следующей группы посетителей
try {sleep(a(100));} catch(InterruptedException e) {}
}
}
Museum museum;
int queue;
static int a (int x) {
return (int) (Math. random() * x) +1;
}
}
Пример 2. Два потока, соединенные каналом ввода-вывода. Один поток рисует фейерверк, другой формирует для него цвет
/* Апплет, иллюстрирующий обмен данными с помощью каналов ввода-
* вывода. Апплет производит рисование залпов фейерверка.
* Рисованием фейерверка занимается объект-поток типа
* ZalpThr. Другой поток (типа ColorThr) случайным образом
* генерирует цвет очередной серии залпов.
* Для передачи сгенерированного цвета в объект-поток рисования
* фейерверка используются канальные потоки ввода-вывода,
* которые создаются в объекте-апплете.
*/
import java. awt.*;
import java. applet.*;
import java. io.*;
// класс рисования фейерверка
public class Zalp extends Applet
{
// канальный поток ввода (для чтения сгенерированного цвета)
PipedInputStream in=null;
// канальный поток вывода (для передачи сгенерированного цвета)
PipedOutputStream out=null;
public void init()
{
// создание канальных потоков ввода-вывода
try
{
in = new PipedInputStream();
// поток вывода создается на основе потока ввода
// для организации коммуникационного канала
// между ними
out = new PipedOutputStream(in);
}
catch(IOException ex)
{
}
setBackground(Color. black);
// создание потока рисования фейерверка,
// в качестве параметров конструктора передаются
// поток ввода для получения цвета рисования и
// графический контекст апплета
new ZalpThr(in, getGraphics()).start();
// создание потока генерации цвета фейерверка,
// в качестве параметров конструктора передается
// поток вывода для передачи цвета
new ColorThr(out).start();
}
}
import java. io.*;
// поток генерации цвета фейерверка
class ColorThr extends Thread
{
PipedOutputStream out;
ColorThr(PipedOutputStream out)
{
this. out=out;
}
public void run()
{
while (true)
{
try
{
// генерация компонентов цвета и отправка
// их через канал вывода потоку рисования
// фейерверка
out. write(100+(int)(Math. random()*155));
out. write(100+(int)(Math. random()*155));
out. write(100+(int)(Math. random()*155));
}
catch(IOException ex)
{
}
try
{
// задается пауза до генерации
// следующего цвета
sleep((int)(Math. random()*10000));
}
catch(InterruptedException e)
{ }
}
}
}
import java. awt.*;
import java. io.*;
// класс рисования фейерверка
class ZalpThr extends Thread
{
int M=300,N=300;
int zx, zy;
int zd;
boolean znew=true;
int r, g,b;
PipedInputStream in=null;
Graphics gr;
ZalpThr(PipedInputStream in, Graphics gr)
{
this. in=in;
this. gr=gr;
}
public void run()
{
while (true)
{
if (znew)
{
zx=(int)(Math. random()*M);
zy=(int)(Math. random()*N);
zd=0;
znew=false;
// проверяем наличие данных в потоке ввода
// если они там есть, то считываем их
try
{
if (in. available()>0)
r=in. read();
if (in. available()>0)
g=in. read();
if (in. available()>0)
b=in. read();
}
catch(IOException ex)
{
System. out. println("Exception!!!");
}
}
else
{
zd+=10;
if(zd>=M)
znew=true;
}
paint();
try
{
sleep(50);
}
catch(InterruptedException e)
{
}
}
}
public void paint()
{
int x, y;
int d;
Color col=new Color(r, g,b);
gr. setColor(col);
gr. clearRect(0,0,M, N);
if (zd==0)
{
gr. fillOval(zx, zy,10,10);
}
else if (zd<=M/2)
{
double dvaPI=2*Math. PI;
double step=dvaPI/100;
for (double i=0; i<dvaPI; i+=step)
{
d=zd/2+(int)(Math. random()*zd/2);
x=zx+(int)(d*Math. cos(i));
y=zy-(int)(d*Math. sin(i));
gr. fillOval(x, y,5,5);
}
}
}
}
Пример 3. Чат-сервер
/* Чат-сервер J M Bishop Январь 1997
* Модифицированная версия - Java 1.1 Январь 1998
* Создает сервер для обмена сообщениями.
*
* Подключение клиента:
* telnet x y
* где x и y - имя и порт компьютера,
* на котором запущен сервер.
*
* Иллюстрирует сокеты, ввод-вывод на сокетах
* потоки, синхронизацию и использование списков.
*/
import java. io.*;
import .*;
public class ChatServer {
private static List clientList = new List();
private static int id = 0;
public static void main(String[] args) throws IOException {
// Назначаем порт и создаем сокет.
int port = 8190;
if (args. length > 0)
port = Integer. parseInt(args[0]);
ServerSocket listener = new ServerSocket(port);
System. out. println("The Chat Server is running " +
" on port "+port);
// Ожидаем (слушаем) новых клиентов.
// Для каждого клиента создаем поток-обработчик.
// Добавляем клиента в связный список.
while (true) {
Socket client = listener. accept();
new ChatHandler(client).start();
System. out. println("New client no."+id+
" from "+ client. getInetAddress()+
" on client's port "+client. getPort());
clientList. reset();
clientList. add(client);
id++;
}
}
static synchronized void broadcast
(String message, String name)
throws IOException {
// Посылаем сообщение всем клиентам.
Socket s;
PrintWriter p;
for (clientList. reset();
!clientList. eol(); clientList. succ())
{
s = (Socket)clientList. current();
p = new PrintWriter(s. getOutputStream(), true);
p. println(name+": "+message);
}
}
static synchronized void remove(Socket s) {
// Ищем клиента в списке (по ссылке на его сокет)
// и удаляем его из списка.
Socket t;
for (clientList. reset();
!clientList. eol(); clientList. succ())
{
t = (Socket)clientList. current();
if (t. equals(s))
break;
}
clientList. remove();
id--;
}
}
class ChatHandler extends Thread {
// Класс ChatHandler вызывается из ChatServer:
// один поток для каждого клиента, подключившегося к чату.
private BufferedReader in;
private PrintWriter out;
private Socket toClient;
private String name;
ChatHandler(Socket s) {
toClient = s;
}
public void run() {
try {
// Создаем потоки ввода-вывода для сокета
// и печатаем приглашение.
in = new BufferedReader(new InputStreamReader(
toClient. getInputStream()));
out = new PrintWriter(toClient. getOutputStream(),
true);
out. println("*** Welcome to the Chatter ***");
out. println("Type BYE to end");
out. println("What is your name? ");
out. flush();
String name = in. readLine();
ChatServer. broadcast(name+
" has joined the discussion.", "Chatter");
// Читаем строки сообщения
// и отправляем сообщение всем клиентам.
while (true) {
String s = in. readLine().trim();
// Проверяем первые три символа для BYE.
// Избегаем проблем с разными символами конца строки.
if (s. length() > 2 && s. charAt(0) == 'B' &&
s. charAt(1) == 'Y' && s. charAt(2) == 'E') {
ChatServer. broadcast(name+
" has left the discussion.","Chatter");
break;
}
ChatServer. broadcast(s, name);
}
ChatServer. remove(toClient);
toClient. close();
} catch (Exception e) {
System. out. println("Chatter error: "+e);
}
}
}
class List {
// Класс Список, J M Bishop Октябрь 1997
// Поддерживает список объектов
// в порядке LIFO (Last-in-First-out),
// содержит метод-итератор.
private Node start, now, prev;
public List() {
now = null;
start = null;
prev = null;
}
public void add(Object x) {
if (start == null) {
start = new Node(x, null);
now = start;
} else {
Node T = new Node(x, now. link);
now. link = T;
prev = now;
now = T;
}
}
public void remove() {
if (isempty() || eol()) {
return;
} else {
if (prev == null) {
start = now. link;
} else {
prev. link = now. link;
now = now. link;
}
}
}
public boolean isempty() {
return start == null;
}
public Object current() {
return now. data;
}
public void reset() {
now = start;
prev = null;
}
public boolean eol() {
return now == null;
}
public void succ() {
now = now. link;
if (prev == null)
prev = start;
else
prev = prev. link;
}
class Node {
// Класс Node для хранения объектов,
// которые связаны в список.
Node link;
Object data;
Node(Object d, Node n) {
link = n;
data = d;
}
}
}
Пример 4. HTML-форма, передающая параметры сервлету. Данная форма предназначена для ввода и отсылки данных при оформлении заказа в электронном магазине.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD><TITLE>Оформление заказа</TITLE></HEAD>
<BODY BGCOLOR="#FDF5E6">
<H1 ALIGN="CENTER">Оформление заказа</H1>
<FORM ACTION="/servlet/ShowParameters" METHOD="POST">
Код товара: <INPUT TYPE="TEXT" NAME="itemNum"><BR>
Количество: <INPUT TYPE="TEXT" NAME="quantity"><BR>
Цена за штуку: <INPUT TYPE="TEXT" NAME="price" VALUE="$"><BR>
<HR>
Имя: <INPUT TYPE="TEXT" NAME="firstName"><BR>
Фамилия: <INPUT TYPE="TEXT" NAME="lastName"><BR>
Адрес доставки:
<TEXTAREA NAME="address" ROWS=3 COLS=40></TEXTAREA><BR>
Вид кредитной карты:<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Visa">Visa<BR>
<INPUT TYPE="RADIO" NAME="cardType" VALUE="Master Card">Master Card<BR>
<INPUT TYPE="RADIO" NAME="cardType" VALUE="Amex">American Express<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Discover">Discover<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Java SmartCard">Java SmartCard<BR>
Номер кредитной карты:
<INPUT TYPE="PASSWORD" NAME="cardNum"><BR>
Повторить номер кредитной карты:
<INPUT TYPE="PASSWORD" NAME="cardNum"><BR><BR>
<CENTER>
<INPUT TYPE="SUBMIT" VALUE="Оформить заказ">
</CENTER>
</FORM>
<br>
</BODY>
</HTML>
Сервлет, получающий параметры из HTML-формы. В результате работы сервлета должен быть сформирован HTML-документ, содержащий таблицу с именами переданных параметров и их значениями.
import java. io.*;
import javax. servlet.*;
import javax. servlet. http.*;
import java. util.*;
public class ShowParameters extends HttpServlet
{
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
response. setContentType("text/html");
PrintWriter out = response. getWriter();
String title = "Reading All Request Parameters";
out. println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0"+
" Transitional//EN\">\n" +
"<HTML>\n" +
"<HEAD><TITLE>List of parameters"+
"</TITLE></HEAD>\n" +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<TABLE BORDER=1 ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
"<TH>Parameter Name<TH>Parameter Value(s)");
// создаем объект-перечисление и заполняем его
// именами параметров формы
Enumeration paramNames = request. getParameterNames();
// запускаем цикл перебора элементов перечисления
while(paramNames. hasMoreElements())
{
// получаем следующий элемент перечисления
String paramName = (String)paramNames. nextElement();
out. print("<TR><TD>" + paramName + "\n<TD>");
// создаем массив строк и записываем в него
// переданные из формы значения параметра,
// имя которого хранится в переменной paramName
String[] paramValues =
request. getParameterValues(paramName);
if (paramValues. length == 1) {
// параметр имеет одно значение
String paramValue = paramValues[0];
// проверка на пустоту значения параметра
if (paramValue. length() == 0)
out. println("<I>No Value</I>");
else
out. println(paramValue);
} else {
// параметр имеет много значений (например,
// список со множественным выбором)
out. println("<UL>");
for(int i=0; i<paramValues. length; i++) {
out. println("<LI>" + paramValues[i]);
}
out. println("</UL>");
}
}
out. println("</TABLE>\n</BODY></HTML>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
doGet(request, response);
}
}
Литература
Основная литература, использованная при подготовке данного курса:
1. Бишоп, Дж. Эффективная работа: Java 2 [Текст]: пер. с англ./ Джуди Бишоп. – СПб.: Питер, 2002. – 592 с.
2. Friesen, J. Java 2 by example [Текст] / Jeff Friesen. – Que, 2000. – 848 p.
3. Джамса, К. Изучи сам. Java сегодня [Текст]: пер. с англ. / Крис Джамса. – Мн.: ООО "Попурри", 1996. – 416 с.
4. Холл, М. Сервлеты и Java Server Pages [Текст]: пер. с англ. / Марти Холл. – СПб.: Питер, 2001. – 496 с.
Дополнительная литература:
1. Эккель, Б. Философия Java [Текст]: пер. с англ. / Брюс Эккель. – СПб.: Питер, 2003. – 976 с.
2. Брогден, Б. Электронный магазин на Java и XML [Текст]: пер. с англ. / Б. Брогден, К. Мииник. – СПб.: Питер, 2002. – 400 с.
3. Мугал, Java. Руководство по подготовка к сдаче сертификационного экзамена CX [Текст]: пер. с англ. / Мугал, Расмуссен. – М.: КУДИЦ-ОБРАЗ, 2006. – 688 с.
4. Шилдт, Г. Java 2 v5.0 (Tiger). Новые возможности [Текст]: пер. с англ. / Герберт Шилдт. – СПб.: БХВ-Петербург, 2005. – 196 с.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 |
<HR>
Имя: <INPUT TYPE="TEXT" NAME="firstName"><BR>
Фамилия: <INPUT TYPE="TEXT" NAME="lastName"><BR>
Адрес доставки:
<TEXTAREA NAME="address" ROWS=3 COLS=40></TEXTAREA><BR>
Вид кредитной карты:<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Visa">Visa<BR>
<INPUT TYPE="RADIO" NAME="cardType" VALUE="Master Card">Master Card<BR>
<INPUT TYPE="RADIO" NAME="cardType" VALUE="Amex">American Express<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Discover">Discover<BR>
<INPUT TYPE="RADIO" NAME="cardType"
VALUE="Java SmartCard">Java SmartCard<BR>
Номер кредитной карты:
<INPUT TYPE="PASSWORD" NAME="cardNum"><BR>
Повторить номер кредитной карты:
<INPUT TYPE="PASSWORD" NAME="cardNum"><BR><BR>
<CENTER>
<INPUT TYPE="SUBMIT" VALUE="Оформить заказ">
</CENTER>
</FORM>
<br>
</BODY>
</HTML>
Сервлет, получающий параметры из HTML-формы. В результате работы сервлета должен быть сформирован HTML-документ, содержащий таблицу с именами переданных параметров и их значениями.
import java. io.*;
import javax. servlet.*;
import javax. servlet. http.*;
import java. util.*;
public class ShowParameters extends HttpServlet
{
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
response. setContentType("text/html");
PrintWriter out = response. getWriter();
String title = "Reading All Request Parameters";
out. println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0"+
" Transitional//EN\">\n" +
"<HTML>\n" +
"<HEAD><TITLE>List of parameters"+
"</TITLE></HEAD>\n" +
"<BODY BGCOLOR=\"#FDF5E6\">\n" +
"<H1 ALIGN=CENTER>" + title + "</H1>\n" +
"<TABLE BORDER=1 ALIGN=CENTER>\n" +
"<TR BGCOLOR=\"#FFAD00\">\n" +
"<TH>Parameter Name<TH>Parameter Value(s)");
// создаем объект-перечисление и заполняем его
// именами параметров формы
Enumeration paramNames = request. getParameterNames();
// запускаем цикл перебора элементов перечисления
while(paramNames. hasMoreElements())
{
// получаем следующий элемент перечисления
String paramName = (String)paramNames. nextElement();
out. print("<TR><TD>" + paramName + "\n<TD>");
// создаем массив строк и записываем в него
// переданные из формы значения параметра,
// имя которого хранится в переменной paramName
String[] paramValues =
request. getParameterValues(paramName);
if (paramValues. length == 1) {
// параметр имеет одно значение
String paramValue = paramValues[0];
// проверка на пустоту значения параметра
if (paramValue. length() == 0)
out. println("<I>No Value</I>");
else
out. println(paramValue);
} else {
// параметр имеет много значений (например,
// список со множественным выбором)
out. println("<UL>");
for(int i=0; i<paramValues. length; i++) {
out. println("<LI>" + paramValues[i]);
}
out. println("</UL>");
}
}
out. println("</TABLE>\n</BODY></HTML>");
}
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
doGet(request, response);
}
}
Литература
Основная литература, использованная при подготовке данного курса:
1. Бишоп, Дж. Эффективная работа: Java 2 [Текст]: пер. с англ./ Джуди Бишоп. – СПб.: Питер, 2002. – 592 с.
2. Friesen, J. Java 2 by example [Текст] / Jeff Friesen. – Que, 2000. – 848 p.
3. Джамса, К. Изучи сам. Java сегодня [Текст]: пер. с англ. / Крис Джамса. – Мн.: ООО "Попурри", 1996. – 416 с.
4. Холл, М. Сервлеты и Java Server Pages [Текст]: пер. с англ. / Марти Холл. – СПб.: Питер, 2001. – 496 с.
Дополнительная литература:
1. Эккель, Б. Философия Java [Текст]: пер. с англ. / Брюс Эккель. – СПб.: Питер, 2003. – 976 с.
2. Брогден, Б. Электронный магазин на Java и XML [Текст]: пер. с англ. / Б. Брогден, К. Мииник. – СПб.: Питер, 2002. – 400 с.
3. Мугал, Java. Руководство по подготовка к сдаче сертификационного экзамена CX [Текст]: пер. с англ. / Мугал, Расмуссен. – М.: КУДИЦ-ОБРАЗ, 2006. – 688 с.
4. Шилдт, Г. Java 2 v5.0 (Tiger). Новые возможности [Текст]: пер. с англ. / Герберт Шилдт. – СПб.: БХВ-Петербург, 2005. – 196 с.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 |


