Главная страница
Навигация по странице:

  • Невыполняемый

  • Смерть потока

  • Протокол

  • Программирование. Программирование на Java Конспект лекций (ИТМО 2010). Справочник по языку Java и может использоваться как конспект лекционного курса Системы программирования Интернетприложений


    Скачать 0.85 Mb.
    НазваниеСправочник по языку Java и может использоваться как конспект лекционного курса Системы программирования Интернетприложений
    АнкорПрограммирование
    Дата05.08.2022
    Размер0.85 Mb.
    Формат файлаpdf
    Имя файлаПрограммирование на Java Конспект лекций (ИТМО 2010).pdf
    ТипСправочник
    #641226
    страница4 из 9
    1   2   3   4   5   6   7   8   9
    53

    String words[] = {"canoe", "corozon", "chiquita"};
    String tmp;
    for (int i = 0; i < words.length; i++) {
    for (int j = i+1; j < words.length; j++) {
    if (sp.compare(words[i], words[j]) > 0 {
    tmp = words[i];
    words[i] = words[j];
    words[j] = tmp;
    }
    }
    }
    System.out.println("" + words);
    Класс CollationKey
    Используется для повышения производительности при многочисленных сравнениях строк.
    Пример:
    Collator us = Collator.getInstance(Locale.US);
    String words[] = {"apple", "orange", "lemon", "peach"};
    String tmp;
    CollationKey[] keys = new CollationKey(words.length);
    for (int i = 0; i < words.length; i++) {
    keys[i] = us.getCollationKey(words[i]);
    }
    for (int i = 0; i < keys.length; i++) {
    for (int j = i+1; j < keys.length; j++) {
    if (keys[i].compareTo(keys[j])) > 0 {
    tmp = keys[i];
    keys[i] = keys[j];
    keys[j] = tmp;
    }
    }
    }
    for (CollationKey key : keys) {
    System.out.println(key.getSourceString() + " ");
    }
    54

    Использование легковесных процессов
    Данный раздел посвящен работе с потоками (в некоторых других источниках они получили название легковесные процессы). Поток – отдельная выполняемая последователь-ность в программе. Фактически поток – это способ реализации многозадачности в Java.
    Потоки используются при решении многих задач:

    анимация;

    воспроизведение и обработка звуковых данных;

    обновление и восстановление информации в фоновом режиме;

    ожидание и обработка информации, поступающей по сети.
    При запуске поток получает в свое распоряжение определенную долю ресурсов процессора и, в дальнейшем, работает уже с ней. Говорят, что поток имеет "тело", которое содержит операторы, оно находится в методе run()
    Реализация потока
    Java предусматривает две возможности реализации тела потока:

    для класса определяется интерфейс
    Runnable и используется метод run()
    , а также методы start()
    , stop()
    ;

    постоение класса как потомка класса java.lang.Thread
    Создание потока
    Метод start()
    выполняется каждый раз при обращении к странице, содержащей апплет. Метод проверяет состояние объекта
    Thread
    , которая должна быть описана выше, если значение переменной null
    , то создается новый объект типа
    Thread и вызывается метод start()
    класса
    Thread
    Thread myNewThread;
    public void start() {
    if (myNewThread == null) {
    myNewThread = new Thread(this, "MyNewThreadName");
    myNewThread.start();
    }
    }
    Рассмотрим процесс создания нового объекта
    Thread
    . Наибольший интерес для нас представляет первый аргумент в вызове конструктора
    Thread
    Переменная this указывает на текущий апплет. Этот аргумент должен
    55
    реализовать интерфейс
    Runnable
    , после чего он становится адресатом потока.
    Второй аргумент определяет имя потока.
    Остановка потока
    Когда вы покидаете страницу с апплетом, использующим потоки, вызывается метод stop()
    , основное назначение которого является присвоение объекту типа
    Thread значения null public void stop() {
    myNewThread = null;
    }
    Возможен и другой вариант, а именно непосредственный вызов метода stop myNewThread.stop();
    класса
    Thread
    , но он не всегда приемлем, что связано со следующим: метод stop может быть вызван в "неудачный" момент выполнения метода run()
    , в результате чего поток может не прекратить свое выполнение. При повторном посещении страницы будет вызван метод start и апплет начнет свое выполнение.
    Выполнение потока
    Метод run()
    является "сердцем" потока, именно он определяет назначение не только потока, но и, зачастую, всего класса.
    public void run() {
    while (Thread.currentThread() == clockThread){
    repaint();
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {}
    }
    }
    Как было показано выше, перед остановкой работы апплета, значение потока становится равным null
    . Метод run()
    будет выполняться, пока поток не примет значение null. В данном примере апплет перерисовывает сам себя, затем выполнение потока приостанавливается на 1 секунду (1000 милисекунд).
    При вызове repaint()
    происходит обращение к методу paint()
    , который меняет содержимое экрана.
    public void paint(Graphics g) {
    Date now = new Date();
    g.drawString(now.getHours() + ":" + now.getMinutes() +
    ":" + now.getSeconds(), 5, 10);
    }
    56

    Состояние потока
    Новый поток
    Данное выражение создает новый пустой поток:
    Thread myNewThread = new Thread();
    С таким потоком вы можете совершить следующие действия: запустить или остановить (
    stop()
    , start()
    ). Попытка вызвать любой другой метод работы с потоком приводит к вызову исключения
    IllegalThreadStateException
    Выполняемый
    Thread myNewThread = new Thread();
    myNewThread.start();
    Метод start()
    подготавливает все необходимые ресурсы для запуска потока и передает управление методу run()
    Невыполняемый
    Поток является невыполняемым, если находится в одном из четырех состояний:

    вызван метод sleep

    вызван метод suspend

    вызван метод wait

    поток заблокирован вводом/выводом try {
    Thread.sleep(10000);
    } catch (InterruptedException e) {
    }
    Поток прекратил свое выполнение на 10 секунд. После непродолжительного сна поток возобновляет свою работу. Вызов метода resume()
    для спящего потока не дает результатов.
    Чтобы "разбудить" спящий поток (
    sleep()
    ) необходим процесс ожидания, для возобновления работы потока (
    suspend()
    ) достаточно вызвать метод resume()
    . Если поток ожидает установки какой-то переменной, то прервать это можно при помощи notify или notifyAll
    . Если блокировка по причине ожидание окончания ввода/вывода, то необходимо дождаться конца обмена.
    Смерть потока
    Смерть наступает в двух случаях:

    после выполнения метода stop()
    ;

    по естественным причинам, т.е., когда метод run()
    завершил выполнение.
    57

    Метод isAlive()
    возвращает true
    , если поток отработал метод start()
    и не выполнил метод stop()
    . Если же возвращен false
    , то это либо новый поток, либо он умер.
    Распределение приоритета между потоками
    В классе java.lang.Thread описаны три идентификатора, определяющие приоритеты для потоков.

    MIN_PRIORITY

    NORM_PRIORITY

    MAX_PRIORITY
    При создании потока ему по умолчанию устанавливается
    NORM_PRIORITY
    , изменить приоритет можно путем использования метода setPriority(int)
    Изменение приоритета потока заключается в изменении выделяемого ему промежутка времени.
    Использование нескольких потоков
    Рассмотрим пример использования нескольких потоков в рамках одного приложения.
    import java.applet.Applet;
    class CreatTwoThreads extends Applet {
    public void CreatTwoThreads () {
    new CreatThread1().start();
    new CreatThread2().start();
    }
    }
    class CreatThread1 extends Thread {
    public void run () {
    }
    }
    class CreatThread2 extends Thread {
    public void run () {
    }
    }
    Таким образом, головной класс создает два новых объекта и запускает их на выполнение. Два вновь созданных класса являются независимыми
    58
    полноправными потоками и все действия, описанные в методе run()
    будут выполняться как потоковые.
    Класс java.lang.ThreadGroup
    Класс предназначен для объединения потоков в группы, что, в значительной степени, упрощает работу с потоками и позволяет более гибко управлять их работой. С группой потоков возможны те же основные операции, что и с простым потоком:

    запуск;

    останов;

    установка приоритетов;

    и т.д.
    К тому же для группы потоков можно определять как родителя, так и потомков.
    Методы класса java.lang.Thread
    Условно разделим все методы на те, которые возвращают значения, и те, которые их установливают.
    Первая группа:

    activeCount()
    возвращает текущее число активных потоков в группе;

    currentThread()
    возвращает ссылку на текущий выполняющийся поток;

    getName()
    возвращает имя потока;

    getPriority()
    возвращает приоритет потока;

    getThreadGroup()
    возвращает ссылку на группу, к которой принадлежит поток;

    interrupted()
    возвращает, является ли поток остановленным;

    isAlive()
    возвращает, жив ли поток ;

    isDaemon()
    возвращает, является поток демоном;

    isInterrupted()
    возвращает, остановлен ли поток.
    Вторая группа:

    setDaemon(boolean)
    делает поток демоном;

    setName(String)
    устанавливает имя потока;

    setPriority(int)
    изменение приоритета потока.
    59

    Основы сетевого взаимодействия
    Пакет java.net содержит классы, которые отвечают за различные аспекты сетевого взаимодействия. Классы можно поделить на 2 категории:

    низкоуровневый доступ (адреса, сокеты, интерфейсы)

    высокоуровневый доступ (URI, URL, соединения).
    Классы, входящие в java.net, позволяют организовать передачу данных с помощью протоколов TCP, UDP, HTTP.
    TCP и UDP являются протоколами транспортного уровня. Протоколы имеют следующие особенности.
    Протокол
    TCP
    UDP
    Установление соединения да нет
    Подтверждение доставки сообщений да нет
    При этом протокол TCP имеет более высокую надежность доставки сообщений, а UDP – более высокую скорость передачи данных.
    Работа с адресами
    Адреса хостов в локальной и глобальной сети представляются в виде последовательности чисел, которые получили название IP-адреса. IP-адрес может быть представлен в двух форматах — IPv4 и IPv6.
    Адрес формата IPv4 имеет длину 32 бита, и представляется в виде четырех десятичных чисел от 0 до 255, разделенных точками (192.168.0.1 или
    92.123.155.81).
    Адрес формата IPv6 имеет длину 128 бит, и представляется в виде восьми 16- ричных чисел от 0 до
    FFFF, разделенных двоеточиями
    (1080:0:0:0:8:800:200C:417A).
    Пользователям удобнее иметь дело с именами хостов, представленных в алфавитно-цифровом виде. Для преобразования цифровых адресов в алфавитно-цифровые имена используется служба имен DNS (Domain Name
    Service).
    Для представления IP-адресов и доступа к DNS в Java используется класс
    InetAddress.
    Данный класс имеет два подкласса –
    Inet4Address и
    60

    Inet6Address
    , но они используются редко, так как для большинства приложений хватает функциональности базового класса. Объект класса
    InetAddress содержит IP-адрес и имя хоста.
    Экземпляр класса
    InetAddress можно получить с помощью статических методов класса:
    getLocalHost()
    Возвращает локальный хост getByAddress(String host, byte[] addr)
    Возвращает
    InetAddress с заданным IP- адресом и именем (корректность имени для данного адреса не проверяется)
    getByAddress(byte[] addr)
    Возвращает
    InetAddress с заданным IP- адресом getByName(String host)
    Возвращает
    InetAddress с заданным именем хоста (путем обращения к DNS)
    getAllByName(String host)
    Возвращает массив IP-адресов хоста с заданным именем (путем обращения к DNS)
    Основные методы класса
    InetAddress
    :
    byte[] getAddress()
    Возвращает IP-адрес хоста
    String getHostName()
    Возвращает имя хоста
    Передача данных по протоколу TCP
    Для обеспечения передачи данных по протоколу TCP основным классом является java.net.Socket.
    Конструктор класса
    Socket
    :
    Socket(InetAddress address, int port)
    создает соединение и подключает его к заданному порту по заданному IP- адресу
    Методы класса
    Socket
    :
    InputStream getInputStream()
    возвращает входной поток данных
    OutputStream getOutputStream()
    возвращает выходной поток данных void setSoTimeout(int ms)
    устанавливает время ожидания
    61
    завершения операции чтения из входного потока сокета в милли- секундах. По истечении данного времени выбрасывается исключение
    SocketTimeoutException void close()
    закрывает сокет
    Для реализации сервера, который ожидает запрос от клиента и отвечает на него, используется класс
    ServerSocket
    Конструктор класса
    ServerSocket
    :
    ServerSocket(int port)
    создает подключение на заданном порту
    Методы класса
    ServerSocket
    :
    Socket accept()
    ожидает соединение и устанавливает его.
    void setSoTimeout(int ms)
    устанавливает время ожидания установления соединения в миллисекундах. По истечении данного времени выбрасывается исключение
    SocketTimeoutException void close()
    закрывает сокет
    Последовательность создания TCP-соединения на стороне клиента:
    1
    Получение объекта
    InetAddress
    InetAddress ia =
    InetAddress.getLocalHost();
    2
    Создание сокета. При этом задается адрес (объект
    InetAddress
    ) и порт, к которым будет устанавли- ваться соединение
    Socket soc = new Socket(ia, 8888);
    3
    Получение входного и выход-ного потоков сокета
    InputStream is = soc.getInputStream();
    OutputStream os = soc.getOutputStream();
    4
    Чтение данных из входного и запись данных в выходной поток is.read()
    os.write()
    62

    5
    Закрытие потоков is.close();
    os.close();
    6
    Закрытие сокета soc.close();
    Последовательность создания TCP-соединения на стороне сервера:
    1
    Создание объекта
    ServerSocket
    , который будет принимать соединения на заданный порт
    ServerSocket ss = new
    ServerSocket(8888);
    2
    Ожидание соединения от клиента и получение сокета для коммуникации с клиентом.
    Socket soc = ss.accept();
    3
    Получение входного и выходного потоков сокета
    InputStream is = soc.getInputStream();
    OutputStream os = soc.getOutputStream();
    4
    Чтение данных из входного и запись данных в выходной поток is.read()
    os.write()
    5
    Закрытие потоков is.close();
    os.close();
    6
    Закрытие сокета soc.close();
    Передача данных по протоколу UDP
    При работе с UDP используются следующие основные классы: java.net.DatagramPacket
    (представляющий передаваемое сообщение — датаграмму) и java.net.DatagramSocket
    Конструкторы класса
    DatagramPacket
    :
    DatagramPacket(byte[] buf, int length)
    создает датаграмму из задан-ного массива байтов с задан-ной длиной
    DatagramPacket(byte[] buf, int length,
    InetAddress addr,
    int port)
    создает датаграмму из задан-ного массива байтов с задан-ной длиной, для отправления на заданный адрес по задан-ному порту
    Методы класса
    DatagramPacket
    :
    InetAddress getAddress()
    возвращает адрес int getPort()
    возвращает порт
    63
    byte[] getData()
    возвращает массив данных int getLength()
    возвращает длину данных
    Конструкторы класса
    DatagramSocket
    :
    DatagramSocket()
    создает сокет с использова-нием первого доступного локального порта
    DatagramSocket(int port)
    создает сокет с использова-нием заданного порта
    Методы класса
    DatagramSocket
    :
    void send(DatagramPacket p)
    отсылает заданную датаграмму void receive(DatagramPacket p)
    принимает данные в заданную датаграмму void setSoTimeout(int ms)
    устанавливает время ожидания завершения операции приема датаграммы в миллисекундах. По истечении данного времени создается исключение
    SocketTimeoutException void close()
    закрывает сокет
    Последовательность создания UDP-сокета на стороне сервера:
    1
    Создание объекта
    DatagramSocket
    , который будет принимать соединения на заданный порт и буферов для ввода и вывода
    DatagramSocket ds = new
    DatagramSocket(7777);
    byte[] ib = new byte[256];
    byte[] ob = new byte[256];
    2
    Получение датаграммы от клиента
    DatagramPacket ip = new DatagramPacket(ib,
    ib.length);
    ds.receive(ip);
    3
    Формирование ответа клиенту в виде массива байтов ob
    64

    4
    Формирование датаграммы и отсылка ее клиенту (адрес и порт клиента получаются из полученной от клиента датаграммы)
    InetAddress addr =
    ip.getAddress(); int port = ip.getPort();
    DatagramPacket op =
    new DatagramPacket(ob,
    ob.length, addr, port); ds.send(dp);
    5
    Закрытие сокета ds.close();
    Последовательность создания UDP-сокета на стороне клиента:
    1
    Создание объекта
    DatagramSocket
    (без указания порта) и буферов для ввода и вывода
    DatagramSocket ds = new DatagramSocket();
    byte[] ib = new byte[256];
    byte[] ob = new byte[256];
    2
    Формирование запроса серверу в виде массива байтов ob
    3
    Формирование датаграммы и отсылка ее серверу
    DatagramPacket op = new DatagramPacket(ob,
    ob.length, InetAddress
    .getByName(server_name),
    7777); ds.send(dp);
    4
    Получение ответной датаграммы от сервера
    DatagramPacket ip =
    new DatagramPacket(ib,
    ib.length); ds.receive(ip);
    5
    Закрытие сокета ds.close();
    Работа с URL-соединениями
    URI (Unifrom Resource Identifier) – унифицированный идентификатор ресурса. Представляет собой символьную строку, идентифицирующую какой-либо ресурс (обычно ресурс Интернет).
    URL (Uniform Resource Locator) – унифицированный локатор ресурса.
    Представляет собой подкласс URI, который кроме идентификации дает информацию о местонахождении ресурса.
    65

    Формат URL в общем виде (элементы в квадратных скобках могут отсутствовать):
    [протокол:][//[логин[:пароль]@]хост[:порт]][путь]
    [?запрос][#фрагмент]
    Пакет java.net содержит классы URI и URL для представления URI и URL соответственно, класс
    URLConnection
    , использующийся для создания соединения с заданным ресурсом, и его подкласс
    HttpURLConnection
    , реализующий соединение с ресурсом по протоколу HTTP.
    Рекомендуемая последовательность работы с URL-соединениями:
    1. Создать URI:
    URI uri = new URI("
    http://joe:12345@mail.ru:8080/index.php
    "
    + "?getMail=1&page=2#end");
    URI uri2 = new URI("http", ”joe:12345”, ”mail.ru”,
    8080, ”index.php”,”getMail=1&page=2”,”end”);
    2. Преобразовать URI в URL:
    URL url = uri.toURL();
    3. а) Открыть URL-соединение и поток данных:
    URLConnection uc = url.openConnection();
    uc.connect();
    InputStream is = uc.getInputStream();
    б) Открыть поток данных:
    I
    nputStream is = url.openStream();
    4. Получить данные;
    5. Закрыть поток и соединение:
    is.close(); uc.close();
    Использование
    URLConnection по сравнению с простым открытием потока из
    URL позволяет дополнительно устанавливать параметры соединения, такие как возможность взаимодействия с пользователем, разрешение записи и чтения, а также получать информацию о соединении, такую, как даты создания и модификации, тип, длину и кодировку содержимого.
    1   2   3   4   5   6   7   8   9


    написать администратору сайта