java_sieciowa.pdf

(103 KB) Pobierz
253149210 UNPDF
1. Strumienie:
2. Typowe zastosowania strumieni:
• Czytanie ze standardowego wejścia
BufferedReader br =
new BufferedReader(new InputStreamReader(System.in));
String s = br.readLine();
...
br.close();
• Czytanie ze standardowego wejścia (od JDK 1.6)
Console c = System.console();
String napis = c.readLine("Podaj napis");
c.println("Podałeś "+napis);
...
br.close();
• Czytanie z pliku
BufferedReader br =
new BufferedReader(new FileReader("plik.txt"));
String s = br.readLine();
...
br.close();
• Pisanie do pliku
PrintWriter pr = new PrintWriter(
new BufferedWriter(new FileWriter("plik.txt"))));
pr.println("Ala ma kota");
...
pr.close(); // koniecznie
3. Serializacja
Mechanizm serializacji pozwala na przechowywanie obiektów pomiędzy kolejnymi
wywołaniami programu, a także na przesyłanie obiektów przez sieć.
Klasa obiektu, który ma być przechowywany/przesyłany, musi być serializowalna, tzn. musi
implementować interfejs java.io.Serializable . Jest to interfejs znacznikowy, tzn.
nie posiada żadnych metod.
Jeśli nie chcemy, by jakieś pole obiektu było serializowane, deklarujemy je jako
transient . Pola statyczne nie są serializowane.
//utworzenie strumieni:
ObjectOutputStream out = new ObjectOutputStream(outputStream);
ObjectInputStream in = new ObjectInputStream(inputStream);
//zapisanie obiektu:
out.writeObject(new Wiadomosc());
//odczytanie obiektu
Wiadomosc w = (Wiadomosc) in.readObject();
4. Wykrywanie typów w czasie wykonania (RTTI - run-time type identification)
Czasami otrzymujemy obiekt, ale nie wiemy jakiego dokładnie jest typu. Żeby to sprawdzić,
możemy użyć słowa kluczowego instanceof .
class Zwierz{}
class Byk extends Zwierz{}
...
Zwierz z = new Byk();
if (z instanceof Zwierz){...} // true
if (z instanceof Byk){ // true
Byk b = (Byk) z; // można zrzutować w dół
}
if (Zwierz.class.isInstance(z)){...} //true
Możliwe jest z obiektu klasy Class pobierać informacje o polach, metodach,
konstruktorach danej klasy, argumentach do nich ( z.getClass().getMethods()
itp.); możliwe jest też tworzenie obiektów danej klasy, wywoływanie metod.
Wątki
Wątek ("odchudzony", "lekki" proces) - jest pojedynczym sekwencyjnym przepływem sterowania,
działającym w ramach procesu (oddzielna, niezależna ścieżka wykonania). Pojedynczy proces może
posiadać wiele wątków. Wątki mają wspólną pamięć.
Tworzenie wątku
1. sposób 1
Napisać klasę dziedziczącą po Thread i przesłonić w niej metodę run . Metoda run jest
dla wątku tym, czym metoda main dla tradycyjnego programu bez wątków.
class MojWatek extends Thread{
public void run(){
// działanie wątku
}
}
//...
MojWatek w = new MojWatek();
//...
2. sposób 2
Napisać klasę implementującą interfejs Runnable (z metodą run ) i przekazać obiekt tej
klasy konstruktorowi klasy Thread . Stosuje się w sytuacji, gdy klasa już dziedziczy z
czegoś innego.
class MojWatek implements Runnable{
public void run(){
// działanie wątku
}
}
//...
MojWatek d = new MojWatek();
Thread watek = new Thread(d);
//...
3. Klasa java.lang.Thread
1. Konstruktor – może brać argument typu String , który jest nazwą wątku (lub typu
Runnable - patrz wyżej); można potem pobrać nazwę wątku przez getName()
2. Metoda run – główne zadanie wątku; zwykle zawiera pewien rodzaj pętli, która
wykonuje się aż wątek nie będzie nam potrzebny; przerwanie tej pętli – wewnątrz
metody, albo przez czynniki zewnętrzne; koniec run = koniec wątku
3. Metoda start – służy do uruchomienia wątku, zainicjuje go i wywołuje jego
metodę run
Uruchomienie wątku
Nie wywołujemy bezpośrednio metody run ; uruchamiamy wątek metodą start
public class Test{
public static void main(String[] a){
MojWatek w = new MojWatek();
w.start();
}
}
Przekazanie informacji do wątku
Deklaracja metody run jest ustalona, więc nie można tej metodzie przekazywać
argumentów ani pobierać od niej wartości. Aby przekazać jakieś dane do wątku,
dostarczamy je konstruktorowi, który inicjuje pola w podklasie klasy Thread . Podobnie,
aby odebrać dane od wątku, możemy odwołać się do pól, które wątek wypełnił. Po śmierci
wątku (czyli zakończeniu metody run ) wciąż istnieje obiekt wątku, dlatego możemy się
odwołać do jego pól.
class MojWatek extends Thread{
int daneWejściowe;
int daneWyjściowe;
public MojWatek(int daneWejściowe){
this.daneWejściowe = daneWejściowe;
}
public void run(){
// przetwarzamy dane
// wynik umieszczamy w polu daneWyjściowe
}
}
//...
MojWatek w = new MojWatek(564);
w.start();
w.join(); // czekamy aż wątek skończy działanie
System.out.println("Watek obliczyl:"+w.daneWyjsciowe);
//...
Wstrzymywanie wykonywania wątku i przerywanie wstrzymania
Metoda sleep - przerywa wykonywanie wątku na określoną liczbę milisekund. Wyrzuca
wyjątek InterruptedThread , gdy wątek zostanie przerwany przed upływem podanego
czasu (gdy ktoś wywoła jego metodę interrupt ).
public class SleepyHead extends Thread{
public void run(){
try{
sleep( 1000 * 60 * 60 * 8 );
}catch(InterruptedException ie){
System.err.println ("Przerwanie");
}
}
public static void main(String args[]){
Thread sleepy = new SleepyHead();
sleepy.start();
System.out.println ("Wcisnij enter");
System.in.read();
sleepy.interrupt();
}
}
Stany wątków
1. nowy – obiekt został stworzony (użyto konstruktora), ale nie uruchomiony (nie wywołano
run )
2. uruchamialny – wątek może działać, jeśli mechanizm podziału czasu udostępni mu procesor
(metoda run została wywołana i wątek działa albo czeka na procesor)
3. uśmiercony – metoda run zakończyła się albo wywołano metodę stop (która jest
wycofywana)
4. zablokowany – wykonywanie wątku jest wstrzymane
przyczyna blokady
sposób zakończenia blokady
sleep
-upłynął podany czas
-przerwanie (interrupt)
join
-zakończenie dołączonego wątku
-przerwanie (interrupt)
-powiadomienie (notify, notifyAll)
-upłynął podany czas
-przerwanie (interrupt)
wywołanie operacji wejścia/wyjścia -zakończenie operacji
-wyjątek
wejście do bloku synchronizowanego zwolnienie blokady na synchronizowanym obiekcie
Po odblokowaniu wątek przechodzi do stanu "uruchamialny".
Współdzielenie zasobów
Problem: dwa wątki jednocześnie sięgają do tego samego zasobu (sięgają do tego samego
konta bankowego, drukują na tej samej drukarce, modyfikują tą samą zmienną itp.)
Rozwiązanie: wzajemne wykluczanie, czyli umieszczenie fragmentu kodu wewnątrz
klauzuli blokującej, dzięki której w danej chwili tylko jeden wątek może realizować dany
kod. W Javie wzajemne wykluczanie realizuje się przy pomocy słowa kluczowego
synchronized .
1. Sekcje krytyczne - synchronizacja fragmentu kodu (sekcji krytycznej) wewnątrz metody:
synchronized(obiektSynchronizujący){
//. . .
}
W danej chwili dostęp do takiego fragmentu kodu będzie miał tylko jeden wątek.
2. Synchronizacja metod - można też synchronizować całą metodę odwołującą się do
krytycznego zasobu:
synchronized void f() { . . . }
Jest to synchronizacja na obiekcie bieżącym ( this ) klasy, w którym zdefiniowano metodę.
Uwaga: trzeba synchronizować każdą metodę korzystającą z tego zasobu.
W danej chwili tylko jeden wątek może wykonywać metodę synchronizowaną. Jeśli inny
wątek będzie chciał ją wykonywać, będzie blokowany aż do czasu zakończenia
wykonywania metody przez pierwszy wątek.
3. Metody wait, notify .
Są to metody klasy Object . Można je wywoływać tylko z wnętrza metody
synchronizowanej (lub bloku synchronizowanego) - wątek może czekać na obiekcie
( obiekt.wait() ), do którego ma blokadę. Gdy czeka, zwalnia blokadę do obiektu i
przerywa działanie do momentu, gdy zostanie powiadomiony przez jakiś inny wątek.
Powiadomienie odbywa się przez wywołanie metody notify (przez ten inny wątek).
wait
253149210.001.png
Czekanie jest wykorzystywane do wstrzymywania wykonywania do czasu, gdy dalsze
działanie będzie możliwe (zostanie osiągnięty odpowiedni stan).
Adresy Sieciowe
URL
URL to łańcuch znaków identyfikujący zasoby danych. Składa się z dwóch części:
-nazwa protokołu, np. http, ftp, file, mailto
-nazwa zasobu (zależnie od protokołu): nazwa hosta, numer portu, ścieżka dostępu,
zapytanie itp.
• Tworzenie obiektu URL
Konstruktory mogą wyrzucać wyjątek MalformedURLException , gdy tworzymy URL
z nieznanym protokołem.
Obsługiwane są protokoły (zależnie od implementacji Javy): http, file, ftp, mailto, gopher i
in. [zadanie: sprawdzić, które protokoły są obsługiwane]
• Sprawdzanie atrybutów URL-a
Metody zwracające nazwę protokołu, komputera, pliku, portu itp.: getProtocol,
getHost, getPort, getFile itd.
• Pobieranie danych z URL-a
Metoda openStream – łączy się z zasobem wskazywanym przez URL, zwraca obiekt
InputStream , z którego można czytać.
• Łączenie się z URL-em
Metoda openConnection otwiera gniazdo do wskazanego adresu URL (a więc
nawiązuje połączenie) i zwraca obiekt typu URLConnection , z którego można pobrać
strumień wejściowy (metoda getInputStream ), i wyjściowy (metoda
getOutputStream ).
• Klasy URLEncoder i URLDecoder
Jeśli w URL-u pojawia się jakiś niejednoznaczny znak, np. # lub spacja, powinien być
kodowany za pomocą znaku procentu, po którym występuje dwucyfrowa liczba
szesnastkowa, wyrażająca wartość tego znaku. Statyczna metoda
URLEncoder.encode(String s) koduje wg tej metody
Adresy IP
Klasa InetAddress opisuje adres komputera przez nazwę/domenę oraz przez numer IP.
Ma dwa pola:
- hostName ("słowna" nazwa hosta, np. pwsz.elblag.pl ),
- address (adres w notacji liczbowo-kropkowej, np. 84.40.248.5 )
Pola te nie są publiczne
• Tworzenie obiektu InetAddress
Nie ma publicznych konstruktorów – obiekty tworzymy za pomocą metod statycznych tej
klasy:
- getLocalHost ,
- getByName ,
- getAllByName .
Metody te łączą się z lokalnym serwerem DNS i mogą wyrzucać wyjątek
UnknownHostException .
Zgłoś jeśli naruszono regulamin