Commit ae65b54a by Patryk Czarnik

synchronizacja kont - pozostałe wersje

parent 79ed24f1
...@@ -3,7 +3,7 @@ package p28_watki.b_synchro.v1_metody; ...@@ -3,7 +3,7 @@ package p28_watki.b_synchro.v1_metody;
class Konto { class Konto {
private final int numer; private final int numer;
private int saldo; private int saldo;
private final Osoba wlasciciel; private Osoba wlasciciel;
public Konto(int numer, int saldo, Osoba wlasciciel) { public Konto(int numer, int saldo, Osoba wlasciciel) {
this.numer = numer; this.numer = numer;
...@@ -11,11 +11,14 @@ class Konto { ...@@ -11,11 +11,14 @@ class Konto {
this.wlasciciel = wlasciciel; this.wlasciciel = wlasciciel;
} }
public synchronized Osoba getWlasciciel() {
public Osoba getWlasciciel() {
return wlasciciel; return wlasciciel;
} }
public synchronized void setWlasciciel(Osoba wlasciciel) {
this.wlasciciel = wlasciciel;
}
public int getNumer() { public int getNumer() {
return numer; return numer;
} }
...@@ -24,10 +27,6 @@ class Konto { ...@@ -24,10 +27,6 @@ class Konto {
return saldo; return saldo;
} }
public synchronized String toString() {
return "Konto nr " + numer + ", saldo: " + saldo + ", wł.: " + wlasciciel;
}
public synchronized void wplata(int kwota) { public synchronized void wplata(int kwota) {
if(kwota < 0) { if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " we wpłacie"); throw new IllegalArgumentException("Ujemna kwota " + kwota + " we wpłacie");
...@@ -35,6 +34,12 @@ class Konto { ...@@ -35,6 +34,12 @@ class Konto {
saldo += kwota; saldo += kwota;
notify(); notify();
// System.out.println("I jeszcze coś robię");
// saldo --; // potrącić prowizję
// wątek obudzony z notify musi jeszcze poczekać, aż ja skończę tu robotę
// bo to jeszcze ja zajmuję sekcje "synchorized"
} }
public synchronized void wyplata(int kwota) throws BrakSrodkow { public synchronized void wyplata(int kwota) throws BrakSrodkow {
...@@ -42,7 +47,7 @@ class Konto { ...@@ -42,7 +47,7 @@ class Konto {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " w wypłacie"); throw new IllegalArgumentException("Ujemna kwota " + kwota + " w wypłacie");
} }
if(kwota > saldo) { if(kwota > saldo) {
throw new BrakSrodkow("Brak środków na koncie nr " + numer); throw new BrakSrodkow("Brak środków na koncie nr " + numer);
} }
saldo -= kwota; saldo -= kwota;
...@@ -55,13 +60,31 @@ class Konto { ...@@ -55,13 +60,31 @@ class Konto {
try { try {
while(kwota > saldo) { while(kwota > saldo) {
wait(); wait();
// po obudzeniu (notify) ten wątek na normalnych prawach
// czeka na dostęp do sekcji synchronizowanej
// 1) wątek, który zrobił notify, musi wyjść
// 2) może pojawić się trzeci wątek, który "wepchnie się" do metody synchronizowanej,
// zanim zrobi to TEN wątek obudzony z wait-a
// Również z tego powodu warunek oczekiwania należy sprawdzić ponownie po obudzeniu
// Standardowy zapis - pętla while.
} }
saldo -= kwota; saldo -= kwota;
notify(); notify(); // "budzenie kaskadowe"
} catch (InterruptedException e) { } catch (InterruptedException e) {
// Taki wyjątek pojawi się gdy podczas gdy wątek A śpi (w wait, sleep itp.)
// inny wątek B wywoła na wątku A metodę interrupt
// Zazwyczaj robi się to, gdy kończy się program albo anuluje wątki, które nie będą potrzebne.
// interrupt nie jest normalnym zakończeniem oczekiwania. Warunek logiczny nie został spełniony
// - w takiej sytuacji nie powinniśmy podejmować akcji zmieniających stan,
// ani nie powinnismy kontynuować czekania.
System.err.println(e);
} }
} }
public String toString() {
return "Konto nr " + getNumer() + ", saldo: " + getSaldo() + ", wł.: " + getWlasciciel();
}
} }
package p28_watki.b_synchro.v1_metody;
class Konto_Niepoprawnie {
private final int numer;
private int saldo;
private Osoba wlasciciel;
public Konto_Niepoprawnie(int numer, int saldo, Osoba wlasciciel) {
this.numer = numer;
this.saldo = saldo;
this.wlasciciel = wlasciciel;
}
public synchronized Osoba getWlasciciel() {
return wlasciciel;
}
public synchronized void setWlasciciel(Osoba wlasciciel) {
this.wlasciciel = wlasciciel;
}
public int getNumer() {
return numer;
}
public synchronized int getSaldo() {
return saldo;
}
public synchronized void setSaldo(int saldo) {
this.saldo = saldo;
}
public String toString() {
return "Konto nr " + numer + ", saldo: " + saldo + ", wł.: " + wlasciciel;
}
public void wplata(int kwota) {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " we wpłacie");
}
this.setSaldo(this.getSaldo() + kwota);
// Nawet jeśli getter i setter są synchronizowane, to powyższy zapis jest niepoprawny
// bo to się tłumaczy na
// int stareSaldo = this.getSaldo();
// int noweSaldo = stareSaldo + kwota;
// W TYM momencie inny wątek może też odczytać saldo, zmienić i zapisać
// this.setSaldo(noweSaldo);
// między getem a setem mogą wejść inne wątki
}
public void wyplata(int kwota) throws BrakSrodkow {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " w wypłacie");
}
if(kwota > saldo) {
throw new BrakSrodkow("Brak środków na koncie nr " + numer);
}
this.setSaldo(this.getSaldo() - kwota);
}
}
...@@ -9,7 +9,7 @@ class Przeploty { ...@@ -9,7 +9,7 @@ class Przeploty {
final int KWOTA = 10; final int KWOTA = 10;
Osoba ala = new Osoba("Ala", "Kowalska", LocalDate.now()); Osoba ala = new Osoba("Ala", "Kowalska", LocalDate.now());
Konto konto = new Konto(1, 1000000, ala); Konto konto = new Konto(1, 1000_000, ala);
System.out.println(konto); System.out.println(konto);
......
package p28_watki.b_synchro.v2_bloki;
public class BrakSrodkow extends Exception {
private static final long serialVersionUID = 5262944731342409658L;
public BrakSrodkow() {
super();
}
public BrakSrodkow(String message) {
super(message);
}
}
package p28_watki.b_synchro.v2_bloki;
class Konto {
private final int numer;
private int saldo;
private Osoba wlasciciel;
public Konto(int numer, int saldo, Osoba wlasciciel) {
this.numer = numer;
this.saldo = saldo;
this.wlasciciel = wlasciciel;
}
public synchronized Osoba getWlasciciel() {
return wlasciciel;
}
public synchronized void setWlasciciel(Osoba wlasciciel) {
this.wlasciciel = wlasciciel;
}
public int getNumer() {
return numer;
}
public synchronized int getSaldo() {
return saldo;
}
public void wplata(int kwota) {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " we wpłacie");
}
synchronized(this) {
saldo += kwota;
this.notify();
}
}
public void wyplata(int kwota) throws BrakSrodkow {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " w wypłacie");
}
// Jeśli mamy warunek i w zależności od warunku zmieniamy dane,
// to warunek i operacja zmiany muszą być RAZEM w jednym bloku synchronizowanym.
synchronized(this) {
if(kwota > saldo) {
throw new BrakSrodkow("Brak środków na koncie nr " + numer);
}
saldo -= kwota;
}
}
public void wyplataCzekaj(int kwota) {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " w wypłacie");
}
try {
synchronized(this) {
while(kwota > saldo) {
this.wait();
}
saldo -= kwota;
this.notify();
}
} catch (InterruptedException e) {
System.err.println(e);
}
}
public String toString() {
return "Konto nr " + getNumer() + ", saldo: " + getSaldo() + ", wł.: " + getWlasciciel();
}
}
package p28_watki.b_synchro.v2_bloki;
import java.time.LocalDate;
import java.time.Period;
class Osoba {
private String imie, nazwisko;
private LocalDate dataUrodzenia;
public Osoba() {
}
Osoba(String imie, String nazwisko) {
this.imie = imie;
this.nazwisko = nazwisko;
}
public Osoba(String imie, String nazwisko, LocalDate dataUrodzenia) {
this.setImie(imie);
this.nazwisko = nazwisko;
this.dataUrodzenia = dataUrodzenia;
}
public Osoba(String imie, String nazwisko, String dataUrodzenia) {
// wywołanie innego konstruktora z tej samej klasy
this(imie, nazwisko, LocalDate.parse(dataUrodzenia));
}
public int obliczWiek() {
LocalDate dzisiaj = LocalDate.now();
Period wiek = Period.between(dataUrodzenia, dzisiaj);
return wiek.getYears();
}
@Override
public String toString() {
return imie + " " +nazwisko + " ur." + dataUrodzenia;
}
public String kimJestes() {
return "Jestem osobą";
}
public String getImie() {
return imie;
}
public String getNazwisko() {
return nazwisko;
}
public LocalDate getDataUrodzenia() {
return dataUrodzenia;
}
public void setImie(String imie) {
if(imie == null || imie.isEmpty()) {
throw new IllegalArgumentException("imię nie może być puste");
}
this.imie = imie;
}
public void setNazwisko(String nazwisko) {
this.nazwisko = nazwisko;
}
}
package p28_watki.b_synchro.v2_bloki;
import java.time.LocalDate;
class Przeploty {
public static void main(String[] args) {
final int N = 100_000;
final int KWOTA = 10;
Osoba ala = new Osoba("Ala", "Kowalska", LocalDate.now());
Konto konto = new Konto(1, 1000_000, ala);
System.out.println(konto);
Thread wplacacz = new Thread(() -> {
for(int i = 0 ; i < N; i++) {
konto.wplata(KWOTA);
}
});
Thread wyplacacz = new Thread(() -> {
for(int i = 0; i < N; i++) {
try {
konto.wyplata(KWOTA);
} catch (BrakSrodkow e) {
System.err.println(e.getMessage());
}
}
});
System.out.println("Uruchamiam wątki");
wplacacz.start();
wyplacacz.start();
System.out.println("Czekam na zakończenie");
try {
wplacacz.join();
wyplacacz.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Wątki zakończone, konto na końcu:");
System.out.println(konto);
}
}
package p28_watki.b_synchro.v2_bloki;
import java.io.IOException;
class WyplacanieBezOczekiwania {
static volatile boolean koniec = false;
public static void main(String[] args) {
final Osoba ala = new Osoba("Ala", "Kowalska", "2001-01-01");
final Konto konto = new Konto(1, 1700, ala);
System.out.println("początek " + konto);
Thread wplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
konto.wplata(1000);
System.out.println("wpłacacz: wpłaciłem 1000, saldo = " + konto.getSaldo());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
}
}
});
Thread wyplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
try {
konto.wyplata(100);
} catch (BrakSrodkow e) {
System.err.println("BRAK ŚRODKÓW");
}
System.out.println("wypłacacz: wypłaciłem 100, saldo = " + konto.getSaldo());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
});
wplacacz.start();
wyplacacz.start();
System.out.println("Wątki wystartowały");
System.out.println("Naciśnij enter aby zakończyć");
try {
System.in.read();
} catch (IOException e1) {
}
koniec = true;
try {
wplacacz.join();
wyplacacz.join();
} catch (InterruptedException e) {
System.err.println("INTERRUPTED");
}
System.out.println("na końcu: " + konto);
}
}
package p28_watki.b_synchro.v2_bloki;
import java.io.IOException;
class WyplacanieZOczekiwaniem {
static volatile boolean koniec = false;
public static void main(String[] args) {
final Osoba ala = new Osoba("Ala", "Kowalska", "2001-01-01");
final Konto konto = new Konto(1, 1500, ala);
System.out.println("początek " + konto);
Thread wplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
konto.wplata(1000);
System.out.println("wpłacacz: wpłaciłem 1000, saldo = " + konto.getSaldo());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
}
}
});
Thread wyplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
konto.wyplataCzekaj(100);
System.out.println("wypłacacz: wypłaciłem 100, saldo = " + konto.getSaldo());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
});
wplacacz.start();
wyplacacz.start();
System.out.println("Wątki wystartowały");
System.out.println("Naciśnij enter aby zakończyć");
try {
System.in.read();
} catch (IOException e1) {
}
koniec = true;
try {
wplacacz.join();
wyplacacz.join();
} catch (InterruptedException e) {
System.err.println("INTERRUPTED");
}
System.out.println("na końcu: " + konto);
}
}
package p28_watki.b_synchro.v3_locki;
public class BrakSrodkow extends Exception {
private static final long serialVersionUID = 5262944731342409658L;
public BrakSrodkow() {
super();
}
public BrakSrodkow(String message) {
super(message);
}
}
package p28_watki.b_synchro.v3_locki;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Konto {
private final Lock lock = new ReentrantLock();
private final Condition czekanieNaKase = lock.newCondition();
// można tworzyć osobne condition związane z oczekiwaniem na różne warunki
private final Condition czekanieNaUdzielenieKredytu = lock.newCondition();
private final int numer;
protected int saldo;
private Osoba wlasciciel;
public Konto(int numer, int saldo, Osoba wlasciciel) {
this.numer = numer;
this.saldo = saldo;
this.wlasciciel = wlasciciel;
}
public Osoba getWlasciciel() {
try {
lock.lock();
return wlasciciel;
} finally {
lock.unlock();
}
}
public void setWlasciciel(Osoba wlasciciel) {
try {
lock.lock();
this.wlasciciel = wlasciciel;
} finally {
lock.unlock();
}
}
public int getNumer() {
return numer;
}
public int getSaldo() {
lock.lock();
try {
return saldo;
} finally {
lock.unlock();
}
}
public String toString() {
return "Konto nr " + numer + ", saldo: " + saldo + ", wł.: " + wlasciciel;
}
public void wplata(int kwota) {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " we wpłacie");
}
lock.lock();
saldo += kwota;
czekanieNaKase.signal();
lock.unlock();
}
public void wyplata(int kwota) throws BrakSrodkow {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " w wypłacie");
}
lock.lock();
try {
if(kwota > saldo) {
throw new BrakSrodkow("Brak środków na koncie nr " + numer);
}
saldo -= kwota;
} finally {
lock.unlock();
}
}
public void wyplataCzekaj(int kwota) {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " w wypłacie");
}
lock.lock();
try {
while (kwota > saldo) {
czekanieNaKase.await();
}
saldo -= kwota;
czekanieNaKase.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
package p28_watki.b_synchro.v3_locki;
import java.time.LocalDate;
import java.time.Period;
class Osoba {
private String imie, nazwisko;
private LocalDate dataUrodzenia;
public Osoba() {
}
Osoba(String imie, String nazwisko) {
this.imie = imie;
this.nazwisko = nazwisko;
}
public Osoba(String imie, String nazwisko, LocalDate dataUrodzenia) {
this.setImie(imie);
this.nazwisko = nazwisko;
this.dataUrodzenia = dataUrodzenia;
}
public Osoba(String imie, String nazwisko, String dataUrodzenia) {
// wywołanie innego konstruktora z tej samej klasy
this(imie, nazwisko, LocalDate.parse(dataUrodzenia));
}
public int obliczWiek() {
LocalDate dzisiaj = LocalDate.now();
Period wiek = Period.between(dataUrodzenia, dzisiaj);
return wiek.getYears();
}
@Override
public String toString() {
return imie + " " +nazwisko + " ur." + dataUrodzenia;
}
public String kimJestes() {
return "Jestem osobą";
}
public String getImie() {
return imie;
}
public String getNazwisko() {
return nazwisko;
}
public LocalDate getDataUrodzenia() {
return dataUrodzenia;
}
public void setImie(String imie) {
if(imie == null || imie.isEmpty()) {
throw new IllegalArgumentException("imię nie może być puste");
}
this.imie = imie;
}
public void setNazwisko(String nazwisko) {
this.nazwisko = nazwisko;
}
}
package p28_watki.b_synchro.v3_locki;
public class Podklasa extends Konto {
public Podklasa(int numer, int saldo, Osoba wlasciciel) {
super(numer, saldo, wlasciciel);
}
public void wplata(int kwota) {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " we wpłacie");
}
saldo += kwota;
}
}
package p28_watki.b_synchro.v3_locki;
import java.time.LocalDate;
class Przeploty {
public static void main(String[] args) {
final int N = 100_000;
final int KWOTA = 10;
Osoba ala = new Osoba("Ala", "Kowalska", LocalDate.now());
Konto konto = new Konto(1, 1000_000, ala);
System.out.println(konto);
Thread wplacacz = new Thread(() -> {
for(int i = 0 ; i < N; i++) {
konto.wplata(KWOTA);
}
});
Thread wyplacacz = new Thread(() -> {
for(int i = 0; i < N; i++) {
try {
konto.wyplata(KWOTA);
} catch (BrakSrodkow e) {
System.err.println(e.getMessage());
}
}
});
System.out.println("Uruchamiam wątki");
wplacacz.start();
wyplacacz.start();
System.out.println("Czekam na zakończenie");
try {
wplacacz.join();
wyplacacz.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Wątki zakończone, konto na końcu:");
System.out.println(konto);
}
}
package p28_watki.b_synchro.v3_locki;
import java.io.IOException;
class WyplacanieBezOczekiwania {
static volatile boolean koniec = false;
public static void main(String[] args) {
final Osoba ala = new Osoba("Ala", "Kowalska", "2001-01-01");
final Konto konto = new Konto(1, 1700, ala);
System.out.println("początek " + konto);
Thread wplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
konto.wplata(1000);
System.out.println("wpłacacz: wpłaciłem 1000, saldo = " + konto.getSaldo());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
}
}
});
Thread wyplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
try {
konto.wyplata(100);
} catch (BrakSrodkow e) {
System.err.println("BRAK ŚRODKÓW");
}
System.out.println("wypłacacz: wypłaciłem 100, saldo = " + konto.getSaldo());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
});
wplacacz.start();
wyplacacz.start();
System.out.println("Wątki wystartowały");
System.out.println("Naciśnij enter aby zakończyć");
try {
System.in.read();
} catch (IOException e1) {
}
koniec = true;
try {
wplacacz.join();
wyplacacz.join();
} catch (InterruptedException e) {
System.err.println("INTERRUPTED");
}
System.out.println("na końcu: " + konto);
}
}
package p28_watki.b_synchro.v3_locki;
import java.io.IOException;
class WyplacanieZOczekiwaniem {
static volatile boolean koniec = false;
public static void main(String[] args) {
final Osoba ala = new Osoba("Ala", "Kowalska", "2001-01-01");
final Konto konto = new Konto(1, 1700, ala);
System.out.println("początek " + konto);
Thread wplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
konto.wplata(1000);
System.out.println("wpłacacz: wpłaciłem 1000, saldo = " + konto.getSaldo());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
}
}
});
Thread wyplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
konto.wyplataCzekaj(100);
System.out.println("wypłacacz: wypłaciłem 100, saldo = " + konto.getSaldo());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
});
wplacacz.start();
wyplacacz.start();
System.out.println("Wątki wystartowały");
System.out.println("Naciśnij enter aby zakończyć");
try {
System.in.read();
} catch (IOException e1) {
}
koniec = true;
try {
wplacacz.join();
wyplacacz.join();
} catch (InterruptedException e) {
System.err.println("INTERRUPTED");
}
System.out.println("na końcu: " + konto);
}
}
package p28_watki.b_synchro.v4_semafory;
public class BrakSrodkow extends Exception {
private static final long serialVersionUID = 5262944731342409658L;
public BrakSrodkow() {
super();
}
public BrakSrodkow(String message) {
super(message);
}
}
package p28_watki.b_synchro.v4_semafory;
import java.util.concurrent.Semaphore;
/* Użycie semaforów do takiej synchronizacji jest nietypowe
* - w Javie są mechanizmy prostsze w użyciu.
* Semafory bywają podstawowym mechanizmem synchronizacji na innych platformach,
* ale w Javie nadają się tam, gdzie trzeba "liczyć zasoby" (zob. Afrykarium3).
*/
class Konto {
private final Semaphore mutex = new Semaphore(1);
private final Semaphore kasa = new Semaphore(0);
private int iluCzekaNaKase = 0;
private final int numer;
protected int saldo;
private Osoba wlasciciel;
public Konto(int numer, int saldo, Osoba wlasciciel) {
this.numer = numer;
this.saldo = saldo;
this.wlasciciel = wlasciciel;
}
public Osoba getWlasciciel() {
return wlasciciel;
}
public void setWlasciciel(Osoba wlasciciel) {
this.wlasciciel = wlasciciel;
}
public int getNumer() {
return numer;
}
public int getSaldo() {
return saldo;
}
public String toString() {
return "Konto nr " + numer + ", saldo: " + saldo + ", wł.: " + wlasciciel;
}
public void wplata(int kwota) {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " we wpłacie");
}
try {
mutex.acquire();
saldo += kwota;
if(iluCzekaNaKase > 0) {
kasa.release();
} else {
mutex.release();
}
} catch (InterruptedException e) {
mutex.release();
}
}
public void wyplata(int kwota) throws BrakSrodkow {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " w wypłacie");
}
try {
mutex.acquire();
if(kwota > saldo) {
throw new BrakSrodkow("Brak środków na koncie nr " + numer);
}
saldo -= kwota;
} catch (InterruptedException e) {
} finally {
mutex.release();
}
}
public void wyplataCzekaj(int kwota) {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " w wypłacie");
}
try {
mutex.acquire();
while (kwota > saldo) {
iluCzekaNaKase++;
mutex.release();
kasa.acquire();
iluCzekaNaKase--;
}
saldo -= kwota;
} catch (InterruptedException e) {
} finally {
mutex.release();
}
}
}
package p28_watki.b_synchro.v4_semafory;
import java.time.LocalDate;
import java.time.Period;
class Osoba {
private String imie, nazwisko;
private LocalDate dataUrodzenia;
public Osoba() {
}
Osoba(String imie, String nazwisko) {
this.imie = imie;
this.nazwisko = nazwisko;
}
public Osoba(String imie, String nazwisko, LocalDate dataUrodzenia) {
this.setImie(imie);
this.nazwisko = nazwisko;
this.dataUrodzenia = dataUrodzenia;
}
public Osoba(String imie, String nazwisko, String dataUrodzenia) {
// wywołanie innego konstruktora z tej samej klasy
this(imie, nazwisko, LocalDate.parse(dataUrodzenia));
}
public int obliczWiek() {
LocalDate dzisiaj = LocalDate.now();
Period wiek = Period.between(dataUrodzenia, dzisiaj);
return wiek.getYears();
}
@Override
public String toString() {
return imie + " " +nazwisko + " ur." + dataUrodzenia;
}
public String kimJestes() {
return "Jestem osobą";
}
public String getImie() {
return imie;
}
public String getNazwisko() {
return nazwisko;
}
public LocalDate getDataUrodzenia() {
return dataUrodzenia;
}
public void setImie(String imie) {
if(imie == null || imie.isEmpty()) {
throw new IllegalArgumentException("imię nie może być puste");
}
this.imie = imie;
}
public void setNazwisko(String nazwisko) {
this.nazwisko = nazwisko;
}
}
package p28_watki.b_synchro.v4_semafory;
public class Podklasa extends Konto {
public Podklasa(int numer, int saldo, Osoba wlasciciel) {
super(numer, saldo, wlasciciel);
}
public void wplata(int kwota) {
if(kwota < 0) {
throw new IllegalArgumentException("Ujemna kwota " + kwota + " we wpłacie");
}
saldo += kwota;
}
}
package p28_watki.b_synchro.v4_semafory;
import java.time.LocalDate;
class Przeploty {
public static void main(String[] args) {
final int N = 100_000;
final int KWOTA = 10;
Osoba ala = new Osoba("Ala", "Kowalska", LocalDate.now());
Konto konto = new Konto(1, 1000_000, ala);
System.out.println(konto);
Thread wplacacz = new Thread(() -> {
for(int i = 0 ; i < N; i++) {
konto.wplata(KWOTA);
}
});
Thread wyplacacz = new Thread(() -> {
for(int i = 0; i < N; i++) {
try {
konto.wyplata(KWOTA);
} catch (BrakSrodkow e) {
System.err.println(e.getMessage());
}
}
});
System.out.println("Uruchamiam wątki");
wplacacz.start();
wyplacacz.start();
System.out.println("Czekam na zakończenie");
try {
wplacacz.join();
wyplacacz.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Wątki zakończone, konto na końcu:");
System.out.println(konto);
}
}
package p28_watki.b_synchro.v4_semafory;
import java.io.IOException;
class WyplacanieBezOczekiwania {
static volatile boolean koniec = false;
public static void main(String[] args) {
final Osoba ala = new Osoba("Ala", "Kowalska", "2001-01-01");
final Konto konto = new Konto(1, 1700, ala);
System.out.println("początek " + konto);
Thread wplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
konto.wplata(1000);
System.out.println("wpłacacz: wpłaciłem 1000, saldo = " + konto.getSaldo());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
}
}
});
Thread wyplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
try {
konto.wyplata(100);
} catch (BrakSrodkow e) {
System.err.println("BRAK ŚRODKÓW");
}
System.out.println("wypłacacz: wypłaciłem 100, saldo = " + konto.getSaldo());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
});
wplacacz.start();
wyplacacz.start();
System.out.println("Wątki wystartowały");
System.out.println("Naciśnij enter aby zakończyć");
try {
System.in.read();
} catch (IOException e1) {
}
koniec = true;
try {
wplacacz.join();
wyplacacz.join();
} catch (InterruptedException e) {
System.err.println("INTERRUPTED");
}
System.out.println("na końcu: " + konto);
}
}
package p28_watki.b_synchro.v4_semafory;
import java.io.IOException;
class WyplacanieZOczekiwaniem {
static volatile boolean koniec = false;
public static void main(String[] args) {
final Osoba ala = new Osoba("Ala", "Kowalska", "2001-01-01");
final Konto konto = new Konto(1, 1700, ala);
System.out.println("początek " + konto);
Thread wplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
konto.wplata(1000);
System.out.println("wpłacacz: wpłaciłem 1000, saldo = " + konto.getSaldo());
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
}
}
}
});
Thread wyplacacz = new Thread(new Runnable() {
public void run() {
while (!koniec) {
konto.wyplataCzekaj(100);
System.out.println("wypłacacz: wypłaciłem 100, saldo = " + konto.getSaldo());
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
});
wplacacz.start();
wyplacacz.start();
System.out.println("Wątki wystartowały");
System.out.println("Naciśnij enter aby zakończyć");
try {
System.in.read();
} catch (IOException e1) {
}
koniec = true;
try {
wplacacz.join();
wyplacacz.join();
} catch (InterruptedException e) {
System.err.println("INTERRUPTED");
}
System.out.println("na końcu: " + konto);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment