Завершение потока second

завершение потока First

завершение main

Не обращая внимания на вызов способа join()для потока tr1, поток tr2 будет трудиться, в отличие от потока main, что сможет продолжить собственный исполнение лишь по завершении потока tr1.

Вызов способа yield() для исполняемого потока обязан приводить к приостановке потока на некий квант времени, чтобы другие потоки имели возможность делать собственные действия. Но в случае если требуется надежная остановка потока, то направляться применять его очень осторожно либо по большому счету применить второй метод.

// пример # 5 : задержка потока: YieldRunner.java

package chapt14;

public class YieldRunner {

public static void main(String[] args) {

new Thread() {

public void run() {

System.out.println(старт потока 1);

Thread.yield();

System.out.println(завершение 1);

}

}.start();

new Thread() {

public void run() {

направляться.out.println(старт потока 2);

System.out.println(завершение 2);

}

}.start();

}

}

В следствии возможно выведено:

старт потока 1

старт потока 2

завершение 2

завершение 1

Активизация способа yield() в коде способа run()первого объекта потока приведет к тому, что, вероятнее, первый поток будет остановлен на некий квант времени, что предоставит шанс второму потоку запуститься и выполнить собственный код.

Потоки-демоны

Потоки-демоны трудятся в фоновом режиме вместе с программой, но не являются неотъемлемым элементом программы. В случае если какой-либо процесс может выполняться на фоне работы главных его деятельность и потоков выполнения содержится в обслуживании главных потоков приложения, то таковой процесс возможно запущен как поток-демон. Посредством способа setDaemon(boolean value), позванного снова созданным потоком до его запуска, возможно выяснить поток-демон. Способ boolean isDaemon() разрешает выяснить, есть ли указанный поток демоном либо нет.

/* пример # 6 : выполнение и запуск потока-демона: DemoDaemonThread.java */

package chapt14;

class T extends Thread {

public void run() {

try {

if (isDaemon()){

System.out.println(старт потока-демона);

sleep(10000); // заменить параметр на 1

} else{

System.out.println(старт простого потока);

}

} catch (InterruptedException e) {

System.err.print(Error + e);

} finally {

if (!isDaemon())

System.out.println(

завершение простого потока);

Else

System.out.println(

завершение потока-демона);

}

}

}

package chapt14;

public class DemoDaemonThread {

public static void main(String[] args) {

T usual = new T();

T daemon = new T();

daemon.setDaemon(true);

daemon.start();

usual.start();

System.out.println(

последний оператор main);

}

}

В следствии запуска и компиляции, быть может, будет выведено:

последний оператор main

старт потока-демона

старт простого потока

завершение простого потока

Поток-демон (из-за вызова способа sleep(10000)) опоздал завершить исполнение собственного кода до завершения главного потока приложения, связанного с способом main(). Базисное свойство потоков-демонов содержится в возможности главного потока приложения завершить исполнение потока-демона (в отличие от простых потоков) с окончанием кода способа main(), не обращая внимания на то, что поток-демон еще трудится. В случае если уменьшать время задержки потока-демона, то он может успеть завершить собственный исполнение до завершения работы главного потока.

Потоки в графических приложениях

Добавить анимацию в апплет возможно при применении потоков. Поток, ассоциированный с апплетом, направляться запускать тогда, в то время, когда апплет делается видимым, и останавливать при сворачивании браузера. В этом случае способ
repaint() обновляет экран, тогда как программа выполняется. Поток формирует анимационный эффект повторением вызова способа paint() и отображением графики в новой позиции.

/* пример # 7 : освобождение ресурсов апплетом: GraphicThreadsDemo.java */

package chapt14;

import java.awt.Color;

import java.awt.Container;

import java.awt.Graphics;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

public class GraphicThreadsDemo extends JFrame {

JPanel panel = new JPanel();

Graphics g;

JButton btn = new JButton(Добавить шарик);

int i;

public GraphicThreadsDemo() {

setBounds(100, 200, 270, 350);

Container contentPane = getContentPane();

contentPane.setLayout(null);

btn.setBounds(50, 10, 160, 20);

contentPane.add(btn);

panel.setBounds(30, 40, 200, 200);

panel.направляться(Color.WHITE);

contentPane.add(panel);

btn.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent ev) {

new BallThread(panel).start();

i++;

repaint();

}

});

}

public static void main(String[] args) {

GraphicThreadsDemo frame =

new GraphicThreadsDemo();

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.setVisible(true);

}

public void paint(Graphics g){

super.paint(g);

g.drawString(Количество шариков: + i, 65, 300);

}

}

class BallThread extends Thread {

JPanel panel;

private int posX, posY;

private final int BALL_SIZE = 10;

private double alpha;

private int SPEED = 4;

BallThread(JPanel p) {

this.panel = p;

//задание начальной позиции и направления шарика

posX = (int)((panel.getWidth() — BALL_SIZE)

* Math.random());

posY = (int)((panel.getHeight() — BALL_SIZE)

* Math.random());

alpha = Math.random() * 10;

}

public void run() {

while(true) {

posX += (int)(SPEED * Math.cos(alpha));

posY += (int)(SPEED * Math.sin(alpha));

//вычисление угла отражения

if( posX = panel.getWidth() — BALL_SIZE )

alpha = alpha + Math.PI — 2 * alpha;

else if( posX

alpha = Math.PI — alpha;

if( posY = panel.getHeight() — BALL_SIZE )

alpha = -alpha;

else направляться( posY

alpha = -alpha;

paint(panel.getGraphics());

}

}

public void paint(Graphics g) {

//прорисовка шарика

g.setColor(Color.BLACK);

g.fillArc(posX, posY, BALL_SIZE, BALL_SIZE, 0, 360);

g.setColor(Color.WHITE);

g.drawArc(posX + 1, posY + 1, BALL_SIZE,

BALL_SIZE, 120, 30);

try {

sleep(30);

} catch(InterruptedException e) {

e.printStackTrace();

}

//удаление шарика

g.setColor(panel.getBackground());

g.fillArc(posX, posY, BALL_SIZE, BALL_SIZE, 0, 360);

}

}

Завершение потока second

Рис.14.2.Потоки в апплетах

При вызове способа stop() апплета поток перестает существовать, поскольку ссылка на него устанавливается в nullи освобождает ресурсы. Для следующего запуска потока нужно снова инициализировать ссылку и привести к методу start() потока.

Способы synchronized

Частенько появляется обстановка, в то время, когда пара потоков, обращающихся к некоему неспециализированному ресурсу, начинают мешать друг другу; более того, они смогут повредить данный неспециализированный ресурс. К примеру, в то время, когда два потока записывают данные в файл/объект/поток. Для предотвращения таковой ситуации может употребляться главное слово synchronized. Синхронизации не требуют лишь атомарные процессы по записи/чтению, не превышающие по количеству 32 бит.

Как пример будет рассмотрен процесс записи информации в файл двумя соперничающими потоками. В способе main() классa SynchroThreads создаются два потока. В этом же способе создается экземпляр класса Synchro, содержащий поле типа FileWriter, которое связано с файлом на диске. Экземпляр Synchro передается в качестве параметра обоим потокам. Первый поток записывает строчок способом writing() в экземпляр класса Synchro. Второй поток кроме этого пробует сделать запись строчка в тот же самый объект Synchro. Для избежания одновременной записи такие способы объявляются как synchronized. Синхронизированный способ изолирует объект, по окончании чего объект делается недоступным для других потоков. Изоляция снимается, в то время, когда поток всецело выполнит соответствующий способ. Второй метод снятия изоляции – вызов способа wait() из изолированного способа.

В примере показан вариант синхронизации файла для защиты от одновременной записи информации в файл двумя разными потоками.

/* пример # 8 : синхронизация записи информации в файл : MyThread.java : Synchro.java : SynchroThreads.java */

package chapt14;

import java.io.*;

public class Synchro {

private FileWriter fileWriter;

public Synchro(String file) throws IOException {

fileWriter = new FileWriter(file, true);

}

public void close() {

try {

fileWriter.close();

} catch (IOException e) {

e.printStackTrace();

}

}

public synchronized void writing(String str, int i) {

try {

System.out.print(str + i);

fileWriter.append(str + i);

Thread.sleep((long)(Math.random() * 50));

System.out.print(- + i + );

fileWriter.append(- + i + );

} catch (IOException e) {

System.err.print(неточность файла);

e.printStackTrace();

} catch (InterruptedException e) {

System.err.print(неточность потока);

e.printStackTrace();

}

}

}

package chapt14;

public class MyThread extends Thread {

private Synchro s;

public MyThread(String str, Synchro s) {

super(str);

this.s = s;

}

public void run() {

for (int i = 0; i 5; i++) {

s.writing(getName(), i);

}

}

}

package chapt14;

import java.io.*;

public class SynchroThreads {

public static void main(String[] args) {

try {

Synchro s = new Synchro(c:\\temp\\data.txt);

MyThread t1 = new MyThread(First, s);

MyThread t2 = new MyThread(Second, s);

t1.start();

t2.start();

t1.join();

t2.join();

s.close();

} catch (IOException e) {

System.err.print(неточность файла);

e.printStackTrace();

} catch (InterruptedException e) {

System.err.print(неточность потока);

e.printStackTrace();

}

}

}

В следствии в файл будет выведено:

First0-0 Second0-0 First1-1 Second1-1 First2-2

Second2-2 First3-3 Second3-3 First4-4 Second4-4

Код выстроен так, что при отключении синхронизации способа writing() при его вызове одним потоком второй поток может вклиниться и произвести запись собственной информации, не обращая внимания на то, что способ не завершил запись, инициированную первым потоком.

Вывод в этом случае возможно, к примеру, следующим:

First0Second0-0 Second1-0 First1-1 First2-1 Second2-2 First3-3 First4-2 Second3-3 Second4-4 -4

Инструкция synchronized

Синхронизировать объект возможно не только при помощи способов с соответству-
ющим модификатором, но и при помощи синхронизированного блока кода. В этом случае происходит блокировка объекта, указанного в инструкции synchronized,
и он делается недоступным для других синхронизированных способов и блоков. Простые способы на синхронизацию внимания не обращают, исходя из этого ответственность за грамотную блокировку объектов ложится на программиста.

/* пример # 9 : блокировка объекта потоком: TwoThread.java */

packagechapt14;

public class TwoThread {

public static void main(String args[]) {

final StringBuffer s = new StringBuffer();

new Thread() {

public void run() {

int i = 0;

synchronized (s) {

while (i++ 3) {

s.append(A);

try {

sleep(100);

} catch (InterruptedException e) {

System.на данный момент.print(e);

}

System.out.println(s);

}

}//финиш synchronized

}

}.start();

new Thread() {

public void в один раз() {

int j = 0;

synchronized (s) {

while (j++ 3) {

s.append(B);

System.out.println(s);

}

}//финиш synchronized

}

}.start();

}

}

В следствии запуска и компиляции будет, вероятнее (так как и второй поток может заблокировать объект первым), выведено:

A

AA

AAA

AAAB

AAABB

AAABBB

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

В случае если в коде убрать синхронизацию объекта s, то вывод будет вторым, поскольку второй поток сможет получить доступ к объекту и поменять его раньше, чем первый закончит исполнение цикла.

В следующем примере рассмотрено сотрудничество способов wait() и
notify() при возврате и освобождении блокировки в synchronized блоке. Эти способы употребляются для управления потоками в ситуации, в то время, когда нужно задать определенную последовательность действий без повторного запуска потоков.

Способ wait(), вызванный в синхронизированного блока либо способа, останавливает исполнение текущего потока и освобождает от блокировки захваченный объект, в частности объект lock. Возвратить блокировку объекта потоку возможно вызовом способа notify() для конкретного потока либо
notifyAll() для всех потоков. Вызов возможно осуществлен лишь из другого потока, заблокировавшего, со своей стороны, указанный объект.

/* пример # 10 : сотрудничество wait() и notify(): Blocked.java: Runner.java */

package chapt14;

public class Blocked {

private int i = 1000;

public int getI() {

return i;

}

public void setI(int i) {

this.i = i;

}

public synchronized void doWait() {

try {

System.out.print(Не );

this.wait(); /* остановка потока и

освобождение блокировки*/

System.out.print(сущностей ); // по окончании возврата блокировки

Thread.sleep(50);

} catch (InterruptedException e) {

e.printStackTrace();

}

for (int j = 0; j 5; j++) i/=5;

System.out.print(сверх );

}

}

package chapt14;

public class Runner {

public static void main(String[] args) {

Blocked lock = new Blocked();

new Thread() {

public void run() {

lock.doWait();

}}.start();

try {

Thread.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

synchronized (lock) {// 1

lock.setI(lock.getI() + 2);

System.out.print(преумножай );

lock.notify(); // возврат блокировки

}

synchronized (lock) {// 2

lock.setI(lock.getI() + 3);

//блокировка по окончании doWait()

System.out.print(нужного. );

try {

lock.wait(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

направляться.out.print(= + lock.getI());

}

}

В следствии запуска и компиляции будет выведено следующее сообщение:

Не преумножай сущностей сверх нужного. =3

Задержки потоков способом sleep() употребляются для правильной демонстрации последовательности действий, делаемых потоками. В случае если же в коде приложения убрать все блоки синхронизации, и вызовы способов wait() и notify(), то вывод возможно следующим:

Не сущностей преумножай нужного. =1005сверх

Состояния потока

В классе Thread заявлено внутреннее перечисление State, простейшее использование элементов которого призвано оказать помощь в отслеживании состояний потока в ходе функционирования приложения и, как следствие, в улучшении управления им.

/* пример # 11 : состояния NEW, RUNNABLE, TIMED_WAITING, TERMINATED : ThreadTimedWaitingStateTest.java */

package chapt14;

public class ThreadTimedWaitingStateTest extends Thread {

public void run() {

try{

Thread.sleep(50);

} catch (InterruptedException e) {

System.err.print(неточность потока);

}

}

public static void main(String [] args){

try{

Thread thread = new ThreadTimedWaitingStateTest();

// NEW – поток создан, но ещё не запущен

System.out.println(1: + thread.getState());

thread.start();

// RUNNABLE – поток запущен

System.out.println(2: + thread.getState());

Thread.sleep(10);

// TIMED_WAITING

// поток ожидает некое время завершения работы другого потока

System.out.println(3: + thread.getState());

thread.join();

// TERMINATED – поток завершил исполнение

System.out.println(4: + thread.getState());

} catch (InterruptedException e) {

System.err.print(неточность потока);

}

}

}

В следствии запуска и компиляции будет выведено:

NEW

RUNNABLE

TIMED_WAITING

TERMINATED

/* пример # 12 : состояния BLOCKED, WAITING : ThreadWaitingStateTest.java */

package chapt14;

public class ThreadWaitingStateTest extends Thread {

public void run() {

try {

synchronized (this) {

wait();

}

} catch (InterruptedException e) {

System.err.print(неточность потока);

}

}

public static void main(String[] args) {

try {

Thread thread = new ThreadWaitingStateTest();

thread.start();

synchronized (thread) {

Thread.sleep(10);

// BLOCKED – because thread attempting to acquire a lock

System.out.println(1: + thread.getState());

}

Thread.sleep(10);

// WAITING – способ wait() в synchronized

// останавил поток и высвободил блокировку

System.out.println(2: + thread.getState());

thread.interrupt();

} catch (InterruptedException e) {

System.err.print(неточность потока);

}

}

}

В следствии запуска и компиляции будет выведено:

BLOCKED

WAITING

Потоки в J2SE 5

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

В версии 1.5 языка добавлены пакеты классов java.util.concurrent.locks, java.util.concurrent.atomic,java.util.concurrent, возможности которых снабжают более высокую производительность, масштабируемость, построение потокобезопасных блоков параллельных (concurrent) классов, вызов утилит синхронизации, применение семафоров, ключей и atomic-переменных.

Возможности синхронизации существовали и ранее. Фактически это означало, что синхронизированные объекты блокировались, не смотря на то, что нужно это было далеко не всегда. К примеру, поток, изменяющий одну часть объекта Hashtable, блокировал работу вторых потоков, каковые желали прочесть (кроме того не поменять) совсем другую часть этого объекта. Исходя из этого введение дополнительных возможностей, которые связаны с синхронизаций потоков и блокировкой ресурсов достаточно логично.

Ограниченно потокобезопасные (thread safe) коллекции и вспомогательные классы управления потоками сосредоточены в пакете java.util.concurrent. Среди них необходимо отметить:

  • параллельные классы очередей ArrayBlockingQueue (FIFO очередь с фиксированой длиной), PriorityBlockingQueue (очередь с приоритетом) и ConcurrentLinkedQueue (FIFO очередь с нефиксированой длиной);
  • параллельные аналоги существующих синхронизированых классов-коллекций ConcurrentHashMap (аналог Hashtable) и
    CopyOnWriteArrayList (реализация List, оптимизированная для случая, в то время, когда количество итераций многократно превосходит количество удалений и вставок);
  • механизм управления заданиями, основанный на возможностях класса Executor, включающий пул потоков и работу их планирования;
  • высокопроизводительный класс Lock, поддерживающий ограниченные ожидания снятия блокировки, прерываемые попытки блокировки, очереди блокировки и установку ожидания снятия нескольких блокировок при помощи класса Condition;
  • классы атомарных переменных (AtomicInteger, AtomicLong,
    AtomicReference), и их высокопроизводительные аналоги SyncronizedInt и др.;
  • классы синхронизации неспециализированного назначения, такие как Semaphore, CountDownLatch (разрешает потоку ожидать завершения нескольких операций в других потоках), CyclicBarrier (разрешает нескольким потокам ожидать момента, в то время, когда они все достигнут какой-либо точки) и Exchanger (разрешает потокам синхронизироваться и обмениваться информацией);
  • обработка неотловленных прерываний: класс Thread сейчас поддерживает установку обработчика на неотловленные прерывания (подобное ранее было доступно лишь в ThreadGroup).

Хорошим примером новых возможностей есть синхронизация коллекции типа Hashtable. Объект Hashtable синхронизируется полностью, и в случае если один поток занял кэш остальные потоки вынуждены ожидать освобождения объекта. При же применения нового класса ConcurrentHashMap фактически все операции чтения смогут проходить в один момент, записи и операции чтения фактически не задерживают друг друга, и лишь одновременные попытки записи смогут блокироваться. При же применения данного класса как кэша (спецификой которого есть малое записи операций и большое количество – чтения), блокироваться многопоточный код фактически не будет.

В таблице приведено время исполнения (в миллисекундах) программы, применявшей в качестве кэша ConcurrentHashMap и Hashtable. Тесты проводились на двухпроцессорном сервере под управлением Linux. Количество данных для большего количества потоков возрастало.

Количество потоков ConcurrentHashMap Hashtable
1.00 1.03
2.59 32.40
5.58 78.23
13.21 163.48
27.58 341.21
57.27 778.41

// пример # 13 : использование семафора: Sort.java : ArraySort.java

package chapt14;

import java.util.concurrent.*;

public classSort {

public static final int ITEMS_COUNT = 15;

public static double items[];

// семафор,под контролем которого находиться разрешение на доступ к элементам массива

public static Semaphore sortSemaphore =

new Semaphore(0, true);

public static void main(String[] args) {

items = new double[ITEMS_COUNT];

for(int i = 0 ; i items.length ; ++i)

items[i] = Math.random();

newThread(new ArraySort(items)).start();

for(int i = 0 ; i items.length ; ++i) {

/*

* при проверке доступности элемента сортируемого

* массива происходит блокировка главного потока

* до освобождения семафора

*/

sortSemaphore.acquireUninterruptibly();

System.out.println(items[i]);

}

}

}

class ArraySort implements Runnable {

private double items[];

public ArraySort(double items[]) {

this.items = items;

}

public void run(){

for(int i = 0 ; i items.length — 1 ; ++i) {

for(int j = i + 1 ; j items.length ; ++j) {

if( items[i] items[j] ) {

double tmp = items[i];

items[i] = items[j];

items[j] = tmp;

}

}

// освобождение семафора

Sort.sortSemaphore.release();

try {

Thread.sleep(71);

} catch (InterruptedException e) {

System.err.print(e);

}

}

Sort.sortSemaphore.release();

}

}

Задания к главе 14

Вариант А

1. Cоздать апплет с применением потоков: строчок движется горизонтально, отражаясь от границ апплета и меняя наряду с этим случайным образом собственный цвет.

2. Cоздать апплет с применением потоков: строчок движется по диагонали. При достижении границ апплета все знаки строчка случайным образом меняют регистр.

3. Организовать сортировку массива способами Шелла, Хоара, пузырька, на базе двоичного дерева в различных потоках.

4. Реализовать сортировку графических объектов, применяя методы из задания 3.

5. Создать апплет с точкой, движущейся по окружности с постоянной угловой скоростью. Сворачивание браузера должно приводить к трансформации угловой скорости перемещения точки для следующего запуска потока.

6. Изобразить точку, пересекающую с постоянной скоростью окно слева направо (справа налево) параллельно горизонтальной оси. Когда точка доходит до границы окна, сейчас от левого (правого) края с вертикальной координатной y, выбранной посредством датчика случайных чисел, начинает собственный перемещение вторая точка и т.д. Цвет точки кроме этого возможно выбирать посредством датчика случайных чисел. Для каждой точки создается личный поток.

7. Изобразить в приложении верные треугольники, вращающиеся
в плоскости экрана около собственного центра. Каждому объекту соответствует поток с заданным приоритетом.

8. Условие прошлой задачи изменяется так, что центр вращения перемещается от одного края окна до другого с постоянной скоростью параллельно горизонтальной оси.

9. Cоздать фрейм с тремя шариками, в один момент летающими в окне.
С каждым шариком связан собственный поток со своим приоритетом.

10. Два изображения выводятся в окно. После этого они неспешно исчезают
с разной скоростью в разных потоках (случайным образом выбираются точки изображения, и их цвет устанавливается в цвет фона).

11. Условие прошлой задачи поменять на использование результата постепенного “проявления” двух изображений.

Вариант B

Для заданий варианта В главы 4 организовать синхронизированный доступ к ресурсам (файлам). Для каждого процесса создать отдельный поток исполнения.

Тестовые задания к главе 14

Вопрос 14.1.

Дан код:

class Q implements Runnable{

int i = 0;

public int run(){

System.out.println(i = + ++i);

return i;

}}

public class Quest1 {

public static void main(String[] args) {

Q ob = new Q();

ob.run();

}}

При попытке запуска и компиляции будет выведено:

1) i = 0;

2) i = 1;

3) неточность компиляции: создать объект потока возможно лишь посредством инициализации объекта класса Thread либо его наследников;

4) неточность компиляции: неправильно реализован способ run();

5) неточность времени исполнения: поток обязан запускаться способом start().

Вопрос 14.2.

Дан код:

Thread t1=new Thread();

t1.setPriority(7);

ThreadGroup tg=new ThreadGroup(TG);

tg.setMaxPriority(8);

Thread t2=new Thread(tg,t2);

System.out.print(приоритет t1=

+ t1.getPriority());

System.out.print(, приоритет t2=

+ t2.getPriority());

В следствии выполнения и компиляции будет выведено:

1) приоритет t1 = 7, приоритет t2 = 5;

2) приоритет t1 = 7, приоритет t2 = 8;

3) приоритет t1 = 10, приоритет t2 = 8;

4) нет верного.

Вопрос 14.3.

Дан код:

class T1 implements Runnable{

public void run(){

System.out.print(t1 );

} }

class T2 extends Thread{

public void run(){

System.out.print(t2 );

} }

public class Quest3 {

public static void main(String[] args) {

T1 t1 = new T1();

T2 t2 = new T2(t1);

t1.start();

t2.start();

} }

В следствии запуска и компиляции будет выведено:

1) t1 t2;

2) t2 t1;

3) неточность компиляции: способ start() не выяснен в классе T1;

4) неточность компиляции: в классе T2 не выяснен конструктор, принимающий в качестве параметра объект Thread;

5) ничего из перечисленного.

Вопрос 14.4.

Какое из указанных действий приведет к тому, что поток переходит в состояние “пассивный”? (выберите два)

1) вызов способа sleep() без параметра;

2) вызов способа stop();

3) окончание исполнения способа run();

4) вызов способа notifyAll();

5) вызов способа wait() с параметром null.

Вопрос 14.5.

Дан код:

class Quest5 extends Thread {Quest5 () { }Quest5 (Runnable r) { super(r); } public void run() { System.out.print(thread ); } public static void main(String[] args) { Runnable r = new Quest5(); //1Quest5 t = new Quest5(r); //2 t.start(); } }

При попытке запуска и компиляции будет выведено:

1) неточность компиляции в строчке //1;2) неточность компиляции в строчке //2;3) thread;4) thread thread; 5) код будет откомпилирован, но ничего выведено не будет.

Глава 15

СЕТЕВЫЕ ПРОГРАММЫ

Помощь Интернет

Язык Java делает сетевое программирование несложным благодаря наличию особых средств и классов. Большая часть этих классов находится в пакете семь дней.net. Сетевые классы имеют способы для установки сетевых сообщений передачи и соединений запросов. Многопоточность разрешает обрабатывать пара соединений. Сетевые приложения применяют Internet-приложения, к каким относятся Web-браузер, e-mail, сетевые новости, передача файлов. Для таких приложений употребляются сокеты, порты, протоколы TCP/IP, UDP.

Приложения клиент/сервер применяют компьютер, делающий особую программу-сервер, которая в большинстве случаев устанавливается на удаленном компьютере и предоставляет услуги вторым программам-клиентам. Клиент — это программа, приобретающая услуги от сервера. Клиент устанавливает соединение с сервером и пересылает серверу запрос. Сервер осуществляет прослушивание клиентов, приобретает и делает запрос по окончании установки соединения. Итог исполнения запроса возможно возвращен сервером клиенту. сообщения и Запросы представляют собой записи, структура которых определяется применяемыми протоколами.

В стеке протоколов TCP/IP употребляются следующие прикладные протоколы:

HTTP — Hypertext Transfer Protocol (WWW);

NNTP — Network News Transfer Protocol (группы новостей);

SMTP — Simple Mail Transfer Protocol (посылка почты);

POP3 — Post Office Protocol (чтение почты с сервера);

FTP — File Transfer Protocol (протокол передачи файлов).

Любой компьютер из подключенных к сети по протоколу TCP/IP имеет неповторимый IP-адрес, применяемый для установки и идентификации соединения. Это 32-битовое число, в большинстве случаев записываемое как четыре числа, поделённые точками, каждое из которых изменяется от 0 до 255. IP-адрес возможно временным и выделяться динамически для каждого подключения либо быть постоянным, как для сервера. IP-адреса употребляются во внутренних сетевых совокупностях. В большинстве случаев при подключении к Internet вместо числового IP-адреса употребляются символьные имена (к примеру: www.bsu.by), именуемые именами домена. Особая программа DNS (Domain Name Server), располагаемая на отдельном сервере, контролирует адрес и преобразует имя домена в числовой IP-адрес. В случае если в качестве сервера употребляется данный же компьютер без сетевого подключения, в качестве IP-адреса указывается 127.0.0.1 либо localhost. Для явной идентификации одолжений к IP-адресу присоединяется номер порта через двоеточие, к примеру 217.21.43.10:443. Тут указан номер порта 443. Номера портов от 1 до 1024 смогут быть заняты для внутреннего применения, к примеру, в случае если порт очевидно не указан, браузер воспользуется значением по умолчанию: 20–FTP-данные,21–FTP-управление,53–DNS,80–HTTP,25–SMTP,110–POP3,119–NNTP. К серверу возможно подключиться посредством разных портов. Любой порт показывает конкретное место соединения на указанном компьютере и предоставляет определенную услугу.

Для доступа к сети Internet в браузере указывается адрес URL. Адрес URL (Universal Resource Locator) складывается из двух частей – префикса протокола (http, https, ftp и т.д.) и URI (Universal Resource Identifier). URI содержит Internet-адрес, путь и необязательный номер порта к каталогу, содержащему файл, к примеру:

http://www.bsu.by

URI не имеет возможности содержать такие особые знаки, как пробелы, табуляции, возврат каретки. Их возможно задавать через шестнадцатеричные коды. К примеру: %20 обозначает пробел. Другие зарезервированные знаки: знак –разделитель доводов, знак ?–направляться перед доводами запросов, знак + – пробел, знак # – ссылки в страницы (имя_страницы#имя_ссылки).

Выяснить IP-адрес в приложеннии возможно посредством объекта класса InetAddress из пакета java.net.

Класс InetAddress не имеет public-конструкторов. Создать объект класса возможно посредством статических способов. МетодgetLocalHost()возвращает объект класса InetAddress, содержащий IP-имя и адрес компьютера, на котором выполняется программа. Способ getByName(String host)возвращает объект класса InetAddress, содержащий IP-адрес по имени компьютера, применяя пространство имен DNS. IP-адрес возможно временным, разным для каждого соединения, но он остается постоянным, в случае если соединение установлено. Способ getByAddress(byte[] addr)формирует объект класса InetAddress, содержащий имя компьютера, по IP-адресу, представленному в виде массива байт. В случае если компьютер имеет пара IP, то взять их возможно способом getAllByName(String host),возвращающим массив объектов класса InetAddress. В случае если IP для данной автомобили один, то массив будет содержать один элемент. Способ getByAddress(String host, byte[] addr) формирует объект класса InetAddress с заданным именем и IP-адресом, не контролируя существование для того чтобы компьютера. Все эти способы являются потенциальными генераторами необыкновенной обстановке UnknownHostException, и исходя из этого их вызов должен быть обработан посредством throws для способа либо блока try-catch. Проверить доступ к компьютеру сейчас возможно посредством способа boolean isReachable(int timeout), что возвращает true, в случае если компьютер дешёв, где timeout – время ожидания ответа от компьютера в миллисекундах.

Следующая программа демонстрирует при наличии Internet-соединения, как взять IP-адрес текущего компьютера и IP-адрес из имени домена посредством сервера имен доменов (DNS), к которому обращается способ getByName()класса InetAddress.

/* пример # 1 : вывод IP-адреса компьютера и интернет-ресурса : InetLogic.java*/

package chapt15;

import java.net.*;

public class InetLogic {

public static void main(String[] args) {

InetAddress myIP = null;

InetAddress bsuIP = null;

try {

myIP = InetAddress.getLocalHost();

// вывод IP-адреса локального компьютера

System.out.println(Мой IP —

+ myIP.getHostAddress());

bsuIP = InetAddress.getByName(

www.bsu.by);

// вывод IP-адреса БГУ www.bsu.by

System.out.println(BSU —

+ ibaIP.getHostAddress());

} catch (UnknownHostException e) {

// если не удается отыскать IP

e.printStackTrace();

}

}

}

В следствии будет выведено, к примеру:

Мой IP — 172.17.16.14

BSU — 217.21.43.10

Способ getLocalHost() класса InetAddress формирует объект myIP и возвращает IP-адрес компьютера.

/* пример # 2 : присваивание фиктивного имени настоящему ресурсу, заданному через IP : UnCheckedHost.java */

package chapt15;

import java.io.IOException;

import java.net.InetAddress;

import java.net.UnknownHostException;

public class UnCheckedHost {

public static void main(String[] args) {

// задание IP-адреса лаборатории bsu.iba.by в виде массива

byte ip[] ={(byte)217, (byte)21, (byte)43, (byte)10};

try {

InetAddress addr =

InetAddress.getByAddress(University, ip);

System.out.println(addr.getHostName()

+ — cоединение: + addr.isReachable(1000));

} catch (UnknownHostException e) {

System.out.println(адрес недоступен);

e.printStackTrace();

} catch (IOException e) {

System.out.println(неточность потока);

e.printStackTrace();

}

}

}

В следствии будет выведено при подключения к сети Интернет:

University- cоединение:true

Для доступа к ресурсам возможно создать объект класса URL, говорящий о ресурсах в Internet. В следующем примере объект URL употребляется для доступа к HTML-файлу, на что он показывает, и отображает его в окне браузера посредством способа showDocument().

/* пример # 3 : запуск страницы из апплета: MyShowDocument.java */

package chapt15;

import java.awt.Graphics;

import java.net.MalformedURLException;

import java.net.URL;

import javax.swing.JApplet;

public class MyShowDocument extends JApplet {

privateURL bsu = null;

public String getMyURL() {

return http://www.bsu.by;

}

public void paint(Graphics g) {

int timer = 0;

g.drawString(Загрузка страницы, 10, 10);

try {

for (; timer 30; timer++) {

g.drawString(., 10 + timer * 5, 25);

Thread.sleep(100);

}

bsu = new URL(getMyURL());

getAppletContext().showDocument(bsu, _blank);

} catch (InterruptedException e) {

e.printStackTrace();

} catch (MalformedURLException e) {

Видео курс C# Professional. Урок 11. Потоки


Понравилась статья? Поделиться с друзьями: