- Maszyna wirtualna (Java Virtual Machine JVM) wykonuje tzw. kod bajtowy (bytecode):
+ interpretacja kodu pośredniego,
+ dynamiczne ładowanie klas (ładowanie klasy następuje tylko, gdy jej kod ma być wykonany)
- Niezależność od sprzętu: compile once, run everywhere
- Bezpieczeństwo wykonania programu poprzez statyczne typy/klasy i piaskownice (sandboxing).
top
JNI i JRE
- JNI (Java Native Interface) pozwala na bezpośredni dostęp do instrukcji systemu operacyjnego i użycie innych programów.
- JNI jest używany gdy:
+ standardowa biblioteka Javy nie zawiera specyficznych funkcji lub programów,
+ jest potrzeba używania programów napisanych w innym języku.
- Steruje przepływem danych, np. czytanie i zapis danych, dwięk i obraz.
Java Runtime Environment (JRE) implementuje JNI i JVM.
top
Java: API
Interfejs do Programowania Aplikacji (ang. Application Programming Interface - API) jest biblioteka interfejsów i klas standardowo należących do języka Java.
top
Prymitywne typy
boolean - 1 bit
byte - 8 bit int
char - 16 bit unicode
short - 16 bit int
int - 32 bit int
long - 64 bit int
float - 32 bit float
double - 64 bit float
top
Typy Referencyjne
- Klasy są albo zdefiniowane przez użytkownika, albo są zawarte w bibliotece Application Programming Interface (API).
- Klasa Object obejmuje wszystkie inne klasy i zawiera podstawowe metody dostępne poprzez dziedziczenie wszystkim innym klasom.
top
Java: Przekazywanie Wartości Parametrów
- W Jawie wartości parametrów przekazywane są zgodnie z zasadą wywołania przez wartość (ang. call by value).
- Znaczy to tyle, ze podczas wykonania metody aktualne wartości jej parametrów są kopiowane do nowych zmiennych, a po jej wykonaniu przywracane parametrom.
- W konsekwencji, metoda nie zmienia wartości swoich parametrów.
public class Point {
private double x, y;
public double getX() {
return this.x;
}
public double getY() {
return this.y;
}
public Point(double nx, double ny) {
x = nx;
y = ny;
}
public double sumupANDIncreaseBy(double dx){
return ++this.x + ++this.y + ++dx;
}
public static void main(String[] args) {
Point p1 = new Point(3, 3);
double r = 5;
System.out.println("p1.x = " + p1.getX() + ", p1.y = " + p1.getY() + "; " + "p1.sumupANDIncreaseBy(r) results in "
+ p1.sumupANDIncreaseBy(5)+ ", p1.x = " + p1.getX() + ", p1.y = " + p1.getY() + ", r = " + r);
}
}
top
Czytanie Danych z Konsoli
- W Javie jest możliwe czytanie danych z konsoli i dialog z użytkownikiem.
import java.io.*;
public class InputFloatConsole {
public static void main(String[] args) throws IOException {
BufferedReader console = new BufferedReader(new
InputStreamReader(System.in));
String input = console.readLine();
double x = Float.parseFloat(input);
System.out.println("x = " + x);
}
}
top
Czytanie Danych SWING
import javax.swing.JOptionPane;
public class InputInputSwing {
public static void main(String[] Args){
String input = JOptionPane.showInputDialog("Enter value of type float, Cancel to quit");
double x = Float.parseFloat(input);
System.out.println("x = " + x);
System.exit(0);
}
}
top
Klasy, Klasy Abstrakcyjne i Interfejsy
- Istnieją cztery podstawowe jednostki programistyczne w Javie:
+ klasy konkretne (ang. concrete class),
+ klasy abstrakcyjne (ang. abstract class),
+ klasy wewnętrzne (ang. inner class),
+ interfejsy (ang. interface).
- Podstawową jednostką programistyczną jest klasa. Zawiera ona atrybuty klasowe (class attributes) i obiektowe (object attributes) oraz metody.
- Obiekty zawsze tworzone są w odniesieniu do pewnej klasy konkretnej.
- Posiadają one atrybuty obiektowe, ale nie klasowe, oraz metody.
- Klasy implementują interfejsy (może ich być wiele) oraz dziedziczą (inherit/extend) własności innych klas (w tym abstrakcyjnych).
- Dziedziczenie jest jednokrotne, tzn. klasa może dziedziczyć własności co najwyżej jednej innej klasy (abstrakcyjnej bąd nie).
Klasa abstrakcyjna:
- nie jest możliwe tworzenie obiektów;
- posiada atrybuty i metody;
- metody nie musza być zaimplementowane (słowo kluczowe abstract).
- Abstrakcyjna metoda musi być zaimplementowana przez dziedzicząca klasę konkretną.
- Może ona implementować wiele interfejsów ale dziedziczy własności co najwyżej jednej klasy (także abstrakcyjnej).
Interfejs:
- posiada tylko metody i stale;
- może dziedziczyć tylko z innych interfejsów (może być ich wiele).
Klasa wewnętrzna:
- jest zdefiniowana wewnątrz innej klasy;
- dostęp do niej i jej obiektów ma kod danej klasy i podklas;
- dla innych klas jest niewidoczna;
- pozwala na uniknięcie zaśmiecenia przestrzeni nazw (ang. name spece).
top
Dziedziczenie
- Idea dziedziczenia jest oparta na zasadzie podstawiania sformułowanej przez Barbarę Liskov: obiekt podklasy ma dawać się użyć wszędzie tam, gdzie może być użyty obiekt nadklasy.
- W Javie podklasa może na nowo zdefiniować atrybuty i metody nadklasy, choć te dwa przypadki odpowiadają dwu różnym mechanizmom wiązania.
- Istnieją zasadniczo dwa mechanizmy wiązania: statyczne (w czasie kompilacji) i dynamiczne (w czasie wykonania).
- W Javie atrybuty są wiązane statycznie, a metody dynamicznie zależnie od typu aktualnego parametru.
- Java nie ma wielokrotnego dziedziczenia klas, ale jest za to wielokrotne dziedziczenie interfejsów.
class A {
public String a = "Attribute of A";
}
class B extends A {
private String a = "Attribute of B";
public static void main(String[] args) {
A o = new B();
String x = o.a;
System.out.println(x);
}
} Attributte of A
class A {
public String m() {
return "A";
}
}
class B extends A {
public String m() {
return "B";
}
public static void main(String[] args) {
A o = new B();
System.out.println("Class name of o is " + o.m());
}
} // Class name of o is B
public class A {
public A a;
}
class B extends A {
private A a;
} // powstanie klas binarnych
public class A1 {
public void m(){
}
}
class B1 extends A1 {
private void m(){
}
} // blad kompilacji
top
Odnośniki
W języku Java odnośniki (ang. reference) nie są wskanikami (lub adresami, ang. pointer) ale ich abstrakcjami, bo konkretne adresy mogą się zmieniać np. w skutek zbiorki śmieci i następującej po niej optymalizacji pamięci.
top
API: Klasa Object
- Klasa Object jest korzeniem całego systemu klas i zawiera metody używane przez wszystkie inne klasy, min:
+ protected Object clone() zwraca nową kopię danego obiektu.
+ boolean equals(Object obj) zwraca true jeśli dany obiekt jest równy aktualnemu obiektowi; standardowo działa jako porównanie odnośników. Powinna być przedefiniowana w podklasach.
+ Class>getClass() zwraca klasę obiektu, klasa jest ustalana w czasie wykonania (dokładniej zwracany jest obiekt tę klasę reprezentujący).
+ void notify() budzi pewien inny czekający wątek.
+ void notifyAll() budzi wszystkie inne wątki czekające na monitor.
+ String toString() zwraca napis reprezentujący dany obiekt, powinna być przedefiniowana w podklasie.
+ void wait() każe wątkowi czekać, aż inny wątek wywoła metodę notify() lub notifyAll().
top
Java: Tablice - Arrays
- W Javie tablice są obiektami, dlatego są tworzone z użyciem operatora new:
Animal[] arr = new Animal[4];
for(int i=0 ; i < arr.length ; i++) {
arr[i] = new Animal();
}
- Długość tablicy jest stała.
- Dostęp do długości jest poprzez atrybut length.
top
API: Interfejs Collection
- W Javie, kolekcje są obiektami grupującymi inne, zwykle jednorodne, elementy w jedną całość.
- Kolekcje mają trzy zasadnicze elementy:
+ Interfejs, czyli abstrakcyjny typ danych pozwalający na manipulowanie kolekcja niezależnie od implementacji,
+ Implementację, z reguły ponownie używalną, oraz
+ Algorytmy, które operują na nich jak np. wyszukiwanie lub sortowanie.
top
API: Collection
- Collection
jest parametrycznym interfejsem i zarazem korzeniem hierarchii interfejsów kolekcji.
- Implementujące podklasy: LinkedList, Stack, Vector
- boolean add(E e) dodaje element e do aktualnej kolekcji.
- void clear() usuwa wszystkie elementy z aktualnej kolekcji.
- boolean contains(Object o) sprawdza, czy o jest elementem aktualnej kolekcji.
- int size() zwraca liczbę będąca długością aktualnej kolekcji.
Collection employees;
...
for(Employee e : employees) { //forma zwarta ale z ograniczeniami
e.salary = e.salary + amount;
}
for(ListIterator it = list.iterator(); it.hasNext(); ) {
Employee employee = it.next(); //forma ogolna z uzyciem iteratora
...
}
top
API: SET
Interface Set
- Jest to kolekcja bez powtórzeń zbiór (ang. set) w sensie matematycznym.
- Type Parameters:
+ E - the type of elements maintained by this set
- All Superinterfaces:
+ Collection, Iterable
- All Known Subinterfaces:
+ NavigableSet, SortedSet
- All Known Implementing Classes:
+ AbstractSet, ConcurrentSkipListSet, CopyOnWriteArraySet, EnumSet, HashSet, JobStateReasons, LinkedHashSet, TreeSet
top
API: ListE
List
jest parametrycznym interfejsem implementującym interfejs Collection.
public interface List extends Collection {
E get(int index); // Positional access
E set(int index, E element); //optional
boolean add(E element); //optional
void add(int index, E element); //optional
E remove(int index); //optional
boolean addAll(int index,
Collection extends E> c); //optional
int indexOf(Object o); // Search
int lastIndexOf(Object o);
ListIterator listIterator(); // Iteration
ListIterator listIterator(int index);
List subList(int from, int to); // Range-view
}
top
API: LinkedList
LinkedList
jest parametryczna klasa implementująca interfejs List.
Ta klasa implementuje także Dequeue interfejs pozwalający na użycie LinkedList jako stosu i jako kolejki.
top
API: Vector
- Vector
jest parametryczną klasą implementującą interfejs Collection.
- Wektor jest podobny do tablicy, ale jego długość jest zmienna i teoretycznie nieograniczona.
- insertElementAt(E e, int i) wstawia obiekt e na pozycje i.
- removeElementAt(int i) usuwa element z pozycji i.
- Tworzenie nowych wektorów:
+ Vector employees = new
+ Vector();
top
API: Thread
- Thread jest klasą której obiekty odpowiadają oddzielnym wątkom wykonania. Pozwalają one na współbieżne wykonanie sekwencji instrukcji.
- Standardowo jest tylko jeden wątek związany z metoda main.
- void interrupt() przerywa wykonanie wątku.
- void run() jeśli aktualny wątek został skonstruowany używając obiektu implementującego interfejs Runnable, to ta metoda na tamtym obiekcie zostanie wykonana.
- static void sleep(long ms) sprawia, że aktualnie wykonywany wątek zostaje uśpiony na ms milisekund bez gwarancji dokładności.
top
Błędy i Wyjątki
- Programy zawierają błędy im więcej linii kodu, tym prawdopodobieństwo wystąpienia błędu w kodzie jest większe.
- Typizacja pozwala na wykrycie części z nich, podobnie testowanie, ale nie wszystkich.
- Część błędów w kodzie zostaje ujawniona dopiero w czasie wykonania programu i wtedy trzeba coś z nim zrobić.
- Z drugiej strony, użytkownik może wywołać metodę w niewłaściwy sposób i też wymaga zaradzenia.
- W jawie rozróżnia się błędy (ang. Error) i wyjątki (ang. Exception).
- Oba są podklasami Throwable.
top
Throwable
- Gdy coś jest nie tak, np. program próbuje przeczytać wartość atrybuty obiektu null, wtedy jest rzucany obiekt klasy Throwable.
- Rzucenie takiego obiektu może prowadzić albo do przerwania wykonania programu, albo może być odpowiednio potraktowane.
try { . . . //execute method();
} catch (ErrorOrException e) {
. . . //do something about it
} finally {
. . . //do whatever
}
top
Wyjątki
- Rzucenie obiektu z klasy Throwable sygnalizuje pewnąanomalię.
- Mechanizm wyjątków stosuje się do zaradzania pewnym sytuacjom.
- Mechanizm błędów stosuje się do informowania o tym, ze wystąpił błąd, z którego program nie może usunąć.
- Error, czyli błąd, jest podklasą Throwable.
- Błąd oznacza poważny problem.
- Błędy nie powinny być łapane.
- W rezultacie metoda rzucająca błąd nie musi deklarować go w klauzuli throws.
- Obiekty klasy Exception i jej podklas wskazują na warunki, które mogą być odpowiednio potraktowane.
- Wtedy taki wyjątek jest łapany i odpowiednia procedura, jeśli jest przewidziana, zostaje wykonana.
top
Sprawdzane Wyjątki
- Są dwa rodzaje wyjątków: sprawdzane i nie (ang. checked i unchecked exceptions).
- Sprawdzane wyjątki muszą być albo deklarowane w sygnaturze metody, albo łapane i obsługiwane wewnątrz niej.
try {
System.out.println(Whats your name?);
String name = console.readLine(); //rzucony wątek
System.out.println(Hello, + name + !);
} catch (IOException e) { // łapany i obsługiwany
e.printStackTrace();
System.exit(1);
}
top
Deklaracja Wyjątku
public void ask() throws IOExceptio { // deklaracja wyjątku w sygnaturze metody
System.out.println(Whats your name?);
String name = console.readLine();
System.out.println(Hello, + name + !);
}
IOExceptio musi być obsłużony przez metodę wywołującą lub zadeklarowany w jej sygnaturze.
top
Wyjątki Czasu Wykonania
- Wyjątki czasu wykonania nie muszą być deklarowane w sygnaturze metody.
- Jeśli jednak metoda może rzucić innego rodzaju wyjątek, to ten wyjątek musi być zadeklarowany w jej sygnaturze.
top
Deklaracja Wyjątku
public void credit(int amount) { // deklaracja wyjątku nie jest potrzebna
if(amount < 0)
throw new IllegalArgumentException(Over limit!); // wiadomość o błędzie
balance = balance amount;
}
Ten wyjątek może być albo obsłużony przez metodę wywołującą, albo przekazany dalej.
top
Obsługa Wyjątków
public void transfer(BankAccount target, double amount) {
this.debit(amount); // Metoda wywołana przez inną metodę może rzucić wyjątek.
target.credit(amount);
}
public void transfer(BankAccount target, double amount) {
final double oldBalanceThis = this.balance; // zapisujemy wartość atrybutów
final double oldBalanceTarget = target.balance;
try{
this.debit(amount); // wykonujemy procedurę
target.credit(amount);
} catch (IllegalArgumentException e) {
this.balance = oldBalanceThis;
target.balance = oldBalanceTarget; // w razie rzucenia wyjątku przywracamy wartość atrybutów sprzed wykonania procedury
}
}
try { . . . //execute method();
} catch (ExceptionX e) {
. . . //do something about it
} catch (ExceptionY e) {
. . . //do something about it
} finally { // wykonywany niezaleznie od tego czy wątek zostanie złapany
. . . //do whatever
}
public class C {
public void m() {
}
}
public class D extends C{
public void m() throws IOException {
}
} // błąd kompilacji
public class C {
public void m() throws IOException {
}
}
public class D extends C{
public void m() {
}
} // powstanie klas binarnych
top
Wyjątki a Dziedziczenie
Podklasa musi zachowywać kontrakt nadklasy. W przypadku dziedziczenia metoda w podklasie może rzucać tylko takie sprawdzane wyjątki, które są deklarowane w nadklasie.
class Parent {
public void m() throws IOException {
//. . .
}
}
class Child1 extends Parent {
public void m() { // OK, nie rzuca sprawdzanych wyjątków.
//. . .
}
}
import java.io.IOException;
class Child2 extends Parent { // OK, rzuca wyjątek będący szczególnym przypadkiem wyjątku w nadklasie.
public void m() throws InterruptedIOException {
//. . .
}
}
public void m() {
try {
System.out.println("m throws rune time exception e.");
throw new RuntimeException();
} catch(RuntimeException e){
System.out.println("m handles e.");
throw e;
}
finally{
System.out.println("m executes its finally-part.");
}
}
public void n() {
try {
System.out.println("n calls m.");
m();
} catch(RuntimeException e){
System.out.println("n handles e.");
}
finally{
System.out.println("n executes its finally-part.");
}
}
ODP:
n calls m.
m throws rune time exception e.
m handles e.
m executes its finally-part.
n handles e.
n executes its finally-part.
top
Klonowanie
- Jeśli klasa implementuje interfejs Cloneable, to jest możliwe klonowanie za pomocą standardowej metody.
- Klasa Object zawiera metodę protected Object clone().
- Metoda ta zwraca wyjątek, jeśli obiekt, na którym została wykonana, należy do klasy, która nie implementuje interfejsu Cloneable.
- Jeśli obiekt należy do klasy implementującej Clonable, to metoda ta zwraca nowy obiekt, którego atrybuty są identyczne z atrybutami
klonowanego obiektu.
- W przypadku tablicy i wektora zwracana/y jest nowa tablica/nowy wektor, których elementami są elementy klonowanej tablicy/wektora.
- clone() może być przedefiniowana w podklasach a jej dostępnośćrozszerzona do publicznej:
public Object clone () throws CloneNotSupportedException {
return super.clone();
}
Czasem głębsze klony są potrzebne:
public class A implements Cloneable {
private B b;
public Object clone() throws
CloneNotSupportedException {
A x = (A)this.clone();
if(this.b != null)
x.b = (B)b.clone();
return x;
}
}
Co się stanie gdy metoda clone() zostanie wykonana w następującym przypadku?
public class Child extends Parent {
public Object clone () throws
CloneNotSupportedException {
Child x = (Child)super.clone(); // Rzucony zostanie wyjątek, bo metoda sklonuje this jako obiekt klasy Parent.
}
}
top
Identyczność: equals()
Klasa Object zawiera metodę:
- public boolean equals(Object obj)
- Metoda ta służy do porównywania obiektów.
- W przypadku klasy Object porównywane są obiekty tak, jak w przypadku ==, tj. this.equals(Object o) zwraca true, jeśli this jest tym samym obiektem co o.
- W ogólności jednak metoda ta ma służyć do porównywania stanów obiektów, w szczególności ich atrybutów.
Metoda equals(Object o) powinna spełniać następujące warunki dla x i y różnych od null (porównaj Java API):
- zwrotność: x.equals(x) zwraca true.
- symetria: x.equals(y) zwraca true wtw y.equals(x) zwraca true.
- przechodniość: jeśli x.equals(y) zwraca true i jeśli y.equals(z) zwraca true, to x.equals(z) zwraca true.
- zgodność: wielokrotne wywołanie x.equals(y) stale zwraca true lub stale false.
- x.equals(null) zwraca false.
top
Identyczność: Implementacja
class Point {
public boolean equals(Point o) {
return (this.x == o.x && this.y == o.y);
}
//...
} // przeładowanie uwaga na tę metodę, bo może być niespodziewanie użyta.
public boolean equals(Object o) {
if(!(o instanceof Point)) return false; // przedefiniowanie
else return (this.x == ((Point)o).x && this.y == ((Point)o).y);
}
Identycznosc vs. Klonowanie
- Zasadniczo powinno być tak, że jeśli o1 jest klonem o2 dokonanym na tym samym poziomie co aktualna klasa o2, to o1.equals(o2) zwraca true. (równoważnie o.equals(o.clone()) zwraca true)
- Co więcej: o.clone().getClass() == o.getClass().
Rodzaje
- Rodzaje zapewniają bezpieczeństwo związane z typami.
- W czasie kompilacji jest możliwość sprawdzenia poprawności danej formuły pod względem typów:
- Vector v Vector
;
Klasy Rodzajowe
- Niektóre typy danych i klasy mogą być zaimplementowane niezależnie od konkretnego typu swoich atrybutów i metod, tzn. mogą posiadać parametry będące typami (polimorfizm).
- Vector - kiedy taki parametr zostaje zastąpiony konkretnym typem, taka klasa może być skompilowana.
- Klasa posiada parametry, których wartościami są typy jest nazywana parametryczną lub rodzajową.
Konstruktory
- Niektóre typy danych i klasy mogą być zaimplementowane niezależnie od konkretnego typu swoich atrybutów i metod, tzn. mogą posiadać parametry będące typami.
- Pair(Object) p = new Pair(Object)(null, null);
Możliwa jest jednak automatyczna konwersja typów:
Pair ip = new Pair(3, 5)
Czasem jest konieczne ograniczenie parametrów:
class RestrictedPair {
...
}
- Deklaracja metody rodzajowej z nowym parametrem T:
+ public static T genericM(T[] a)
- Wywołanie metody z aktualnym parametrem:
+ Object s = MyVector.genericM(a);
top
Procesy i Wątki
Proces (ang. process) ma niezależne środowisko wykonania, tj procesor i przestrzeń pamięci.
Procesy są często postrzegane jako programy lub aplikacje. Jednakże to, co użytkownik postrzega jako jeden program, może być zbiorem komunikujących się procesów.
Java pozwala na tworzenie dodatkowych procesów za pomocą obiektów klasy ProcessBuilder.
Wątki (ang. threads) są czasem nazywane lekkimi procesami. Oba rodzaje mają swoje środowisko wykonania, ale istnieją zależnie od procesów
dokładniej wewnątrz nich.
Każdy proces zawiera przynajmniej jeden wątek.
Wątki używają zasobów zawierających ich procesów, w tym pamięci.
Wątki
Wątek wykonania (ang. thread of execution), w skrócie wątek, jest to ciąg instrukcji programistycznych.
Istotą wątków jest to, że mogą być wykonane równocześnie.
Są one zawsze współbieżne ale nie zawsze równoległe.
Jeśli maszyna posiada tylko jeden procesor, to współbieżność może być zapewniona poprzez dzielenie czasu procesora (time slicing).
Istnieją tez mechanizmy pozwalające wątkom na dzielenie się czasem procesora omówimy je na tym wykładzie.
Każdy wątek jest związany z dokładnie jednym obiektem klasy Thread.
- Wątki służą do tego, by
+ zapewnić reaktywność systemu;
+ umożliwić równoczesne wykonanie różnych zadań;
+ monitorować stan urządzeń;
- W czasie tego wykładu zostaną omówione następujące typy wątków:
+ klasa Thread czyli wątek we właściwym tego słowa znaczeniu;
+ interfejs Runnable pozwalający na elastyczne użycie wątków
Wykonanie Sekwencyjne
class Main {
. . .
public static
main(
) { // zacznij
start ...
doThis ... // wykonaj
. . .
doThat ...
finish ... //zakoncz
}
}
Komunikacja wątków
- Komunikacja miedzy wątkami odbywa się za pomocą następującychmetod:
+ currentThread, start, setPriority, yield, run, getPriority, sleep, stop, suspend, resume
- Zbiórka śmieci w Javie odpowiada wątkowi o niskim priorytecie.
Wątki: Klasa Thread
- Klasa Thread implementuje interfejs Runnable, a w szczególności metodę run().
- run() jest wykonywana po utworzeniu wątku.
Synchronizacja: Metody Klasy Threa
sleep(long millis) wstrzymuje wykonanie wątku na przynajmniej millis, choć wątek może być uśpiony na dłużej np. z powodu szeregowania wątków.
yeald() oddaje sterowanie procedurze szeregowania wątków.
setPriority(int newPriority) ustala priorytet wątku.
Wątki: Przykład
class PingPong extends Thread {
String word;
int delay;
PingPong(String whatToSay, int delayTime) {
word = whatToSay;
delay = delayTime;
}
public void run() {
try {
while (true) {
System.out.println(word);
sleep(delay);
}
}catch (InterruptedException e) {
return;
}
}
public static void main( String [] args ) {
PingPong ping = new PingPong( "ping", 33 );
PingPong pong = new PingPong( "PONG", 100 );
ping.start();
pong.start();
}
}
Wątki: Dziedziczenie
Problemy z jedno-dziedziczeniem: dana klasa nie może rozszerzać pewnej dwóch klas. Np. SavingAccount nie może jednocześnie rozszerzać Account i Thread.
Rozwiązanie: implementacja interfejsu Runnable. W Javie klasy mogą rozszerzać dowolnie wiele interfejsów.
Interfejs Runnable
- java.lang.Runnable
+ jest interfejsem;
+ służy do adaptacji dowolnej klasy jako wątku;
+ posiada tylko jedna metodę w sygnaturze
- public void run()
+ Metoda run() musi być zaimplementowana.
Synchronizacja
Wyłączność: tylko jedna metoda synchroniczna może być wykonana na obiekcie inne metody muszą czekać.
wait(), notify() i notifyAll() są metodami zdefiniowanymi w klasie Obiekt służąca do wstrzymania wykonania metod.
Wątki, które nie uzyskały dostępu, wykonują metodę wait(), która jest de facto oczekiwaniem na wykonanie notify() przez inny wątek.
wait() wstrzymuje wykonanie wątku i jednocześnie (atomowo) zwalnia blokadę danego obiektu.
Niepodzielność (atomowość) wyklucza wyścig wątków jak w poprzednim przykładzie zapewnia ją klauzula synchronized.
notify() budzi czekający wątek (zależnie od priorytetu).
Schemat stosowania metody wait:
try {
while(! condition)
wait();
} catch (InterruptedException e) {...}
. . . //kod do wykonania
Synchronizacja: Metody Klasy Object
notifyAll() budzi wszystkie wątki czekające na zmianę warunku.
Aby wywołać notify() i notifyAll() trzeba posiadać blokadę/monitor.
Zakleszczenia
- Są dwa rodzaje zakleszczenia: martwe (ang. deadlock) i żywotne (ang. livelock)
+ Deadlock: w1 blokuje Boba, w2 blokuje Pita, w1 jest zablokowany i czeka na Pita, w2 jest zablokowany i czeka na Boba
+ Livelock: w1 budzi w2 i czeka az condition=true, w2 budzi w1 i czeka az condition=true, i tak w kolko
Aplety: AWT
- Pakiet java.applet zawiera podstawowe interfejsy związane z apletami oraz klasę Applet.
- Applet jest niewielkim programem, który może być uruchomiony przez przeglądarkę lub inny program.
- Applet dziedziczy własności klasy java.awt.Panel, która z kolei dziedziczy własności java.awt.Container itd.
- Pakiet java.awt (Abstract Windowing Toolkit) zawiera interfejsy i klasy potrzebne do konstruowania grafiki.
- Pakiet ten zawiera klasę Graphics. Główne podpakiety to: java.awt.color oraz java.awt.event.
Aplety: Struktura
java.lang.Object
extended by java.awt.Component
extended by java.awt.Container
extended by java.awt.Panel
extended by java.applet.Applet
Aplety: Klasa Graphics
- Klasa Graphics służy do rysowania na komponentach i obrazach.
- Obiekty tej klasy zawierają informacje potrzebne do rysowania i malowania, min.:
+ ustala obiekt klasy Component, na którym będziemy rysować,
+ współrzędne,
+ aktualny kolor,
+ aktualny font.
Aplety: Zdarzenia i Obserwatorzy Zdarzeń
Pojecie zdarzenia jest bardzo nośne i na jego podstawie można oprzeć konstrukcje skomplikowanych interfejsów użytkownika. Istnieje paradygmat programowania zwany programowaniem zdarzeniowym oraz odpowiednie środki programistyczne.
import java.applet.Applet;
// This applet installs a mouse spy.
public class MouseSpyApplet extends Applet {
public MouseSpyApplet() {
MouseSpy listener = new MouseSpy();
addMouseListener(listener);
}
}
- Uruchomienie apletu (np. przez przeglądarkę) powoduje powstanie nowego słuchacza i zarejestrowanie go jako odbiorcy sygnałów z apletu.
- Współrzędne punktu kliknięcia są wypisywane na konsoli dzięki klasie MouseSpy .