Lista tematów
Charakterystyka języka
JNI i JRE
Java: API
Prymitywne typy
Typy Referencyjne
Java: Przekazywanie Wartości Parametrów
Czytanie Danych z Konsoli
Czytanie Danych SWING
Klasy, Klasy Abstrakcyjne i Interfejsy
Dziedziczenie
Odnośniki
API: Klasa Object
Java: Tablice - Arrays
API: Interfejs Collection
API: Collection
API: SET
API: ListE
API: LinkedList
API: Vector
API: Thread
Błędy i Wyjątki
Throwable
Wyjątki
Sprawdzane Wyjątki
Deklaracja Wyjątku
Wyjątki Czasu Wykonania
Deklaracja Wyjątku
Obsługa Wyjątków
Wyjątki a Dziedziczenie
Klonowanie
Identyczność: equals()
Identyczność: Implementacja
Identycznosc vs. Klonowanie
Rodzaje
Klasy Rodzajowe
Konstruktory
Procesy i Wątki
Wątki
Wykonanie Sekwencyjne
Komunikacja wątków
Wątki: Klasa Thread
Synchronizacja: Metody Klasy Threa
Wątki: Przykład
Wątki: Dziedziczenie
Interfejs Runnable
Synchronizacja
Synchronizacja: Metody Klasy Object
Zakleszczenia
Aplety: AWT
Aplety: Struktura
Aplety: Klasa Graphics
Aplety: Zdarzenia i Obserwatorzy Zdarzeń
Aplety: Struktura
Aplety: Struktura
Charakterystyka języka
- Wszystko jest albo prymitywną wartością, klasą, albo obiektem.
- Typami referencyjnymi w jawie są klasy.
- Nie ma zmiennych globalnych.
- Pojedyncze dziedziczenie klas (ang. single inheritance).
- Obiekty są składowane na tzw. składzie (ang. heap) i dzielone przez różne wątki (threads).
- Automatyczne zarządzanie pamięcią -zbiórka śmieci.
- Nie ma metody free() znanej z C++.

- 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, dŸwię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ą wskaŸnikami (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.
  + ClassgetClass() 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 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(“What’s 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(“What’s 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);
}

top


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().

top


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;

top


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ą.

top


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.

top


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

top


Wykonanie Sekwencyjne
class Main {
  . . .
  public static
  main(…) { // zacznij
    start ...
    doThis ... // wykonaj
    . . .
    doThat ...
    finish ... //zakoncz
  }
}

top


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.

top


Wątki: Klasa Thread
- Klasa Thread implementuje interfejs Runnable, a w szczególności metodę run().
- run() jest wykonywana po utworzeniu wątku.

top


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.

top


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();
  }
}

top


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.

top


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.

top


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

top


Synchronizacja: Metody Klasy Object
notifyAll() budzi wszystkie wątki czekające na zmianę warunku.
Aby wywołać notify() i notifyAll() trzeba posiadać blokadę/monitor.

top


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

top


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.

top


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

top


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.

top


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 .