Techniki Zaawansowane
8 godz. 35 min · Java · Full-stack i Programowanie
Rafał SolarskiW poczatkowych lekcjach przyjrzymy sie pokladowi, na jakim bedziemy uruchamiali nasze programy. Wykorzystamy VisualVM do podgladania parametrów JVM. Zobaczymy równiez jakie zasoby sa tam dostepne oraz dowiesz sie jak monitorowac to, czy dobrze z nich korzystamy. Opowiemy Ci tez miedzy innymi o tym, jak zrobic heap i thread dump, oraz jak wlaczyc logi GC.
Kolejne lekcje kursu zostaly poswiecone wyrazeniom regularnym. Wyrazenia regularne mozemy wykorzystac nie tylko do walidacji danych wprowadzania przez uzytkownika, ale równiez do dzielenia tekstu oraz wyluskiwania wystapien wzorców w duzym tekscie. W tym rozdziale dowiemy sie miedzy innymi tego, jak mozemy wykorzystac ten potencjal z poziomu Javy.
Dzieki typom generycznym jestesmy w stanie osiagnac bezpieczenstwo typów w trakcie kompilacji przy zachowaniu elastycznosci pisanego kodu. W nastepnym rozdziale kursu przyjrzymy sie temu, jak mozemy je wykorzystac, oraz w jaki sposób czasami nalezy z tego bezpieczenstwa zrezygnowac.
Interfejsy funkcyjne to sposób na przeniesienie odrobiny swiata programowania funkcyjnego do Javy. Gdy polaczymy je z wyrazeniami lambda oraz API strumieni pozwola nam pisac te sama logike w duzo bardziej przejrzysty sposób.
Kolekcje, czyli listy, mapy, zbiory i kolejki to jedne z najczesciej wykorzystywanych klas w codziennej pracy. To jak dobrze poznamy ich mozliwosci ma ogromny wplyw na to, w jaki sposób bedziemy podchodzili do rozwiazywania wyzwan na naszej drodze.
System plików to zasób bez którego ciezko sobie poradzic. Pozwalaja nam na dostarczanie konfiguracji, danych wejsciowych i wyjsciowych, a przez to równiez integrowanie ze soba calych systemów.W tym rozdziale nauczymy sie korzystac z tych dobrodziejstw w bezpieczny sposób wykorzystujac m.in. IO Streams.
Trzymanie daty w String to niekoniecznie najwygodniejszy sposób. Juz od pewnego czasu Java dysponuje bardzo wygodnym Date&Time API - zobaczymy, co mozemy w nim znalezc.
Wielowatkowosc nie jest prosta... i dlugo tak jeszcze pozostanie. Nawet jesli korzystamy z frameworków, które próbuja ja przed nami ukryc, to ciagle musimy byc swiadomi problemów jakie sie z nia wiaza. W tym rozdziale poznamy glówne problemy na jakie mozna natrafic programujac wielowatkowo w Javie. Poznamy równiez klasy, które zdecydowanie pomoga nam zapanowac nad ta zlozonoscia.
JDBC to najbardziej podstawowy sposób laczenia sie z baza SQL z poziomu Javy. W wielu systemach/aplikacjach stosuje sie rozwiazania ORM takie jak JPA/Hibernate. Mimo wszystko warto wiedziec jak to pod spodem dziala oraz umiec poradzic sobie w aplikacjach, gdzie wybrano bardziej "lekkie" podejscie niz Hibernate.
Na koniec kursu wykorzystamy zdobyta wiedze, aby stworzyc prosta aplikacje pozwalajaca na przechowywanie danych o wydatkach. Po stworzeniu coreu aplikacji, mozesz spróbowac uzupelnic go za pomoca GUI.
Ten kurs stworzony zostal przede wszystkim z mysla o osobach, które juz poznaly podstawy jezyka, takie jak zmienne, mechanizmy kontroli wykonania, klasy, typy generyczne.Jezeli chcesz poczuc sie swobodnie nie tylko jesli chodzi o mechanizmy jezyka, ale równiez pod wzgledem znajomosci standardowej biblioteki Javy - to kurs w sam raz dla Ciebie. Materialy beda przydatne dla studentów, którzy znaja juz podstawowa skladnie Javy; programistów Javy chcacych poszerzyc lub uporzadkowac swoja wiedze; programistów innych jezyków, którzy chca poznac inny stack technologiczny.
Cześć w tej lekcji pokażę ci jeszcze ostatni
z prezentowanych w tym kursie problemów związanych ze współbieżnością a już
w kolejnym odcinku zajmiemy się implementacją pewnego takiego małego projektu tematem
tej lekcji jest deadlock przejdźmy od razu do kodu i zobaczmy
o co chodzi mamy tutaj kawałek jakiegoś kodu ten kod jest współbieżny
wykorzystuje executor service do odpalania jakichś dwóch runnable
tak w tym miejscu no i tutaj jest jakaś akcja prawda mamy
jakieś dwa obiekty klasy bricks warehouse tak czyli powiedzmy
to jest jakaś hurtownia cegieł no i mamy wywołanie
metod transport to z jednego warehouse tak do drugiego
tak do tych hurtowni okej jak teraz to sobie odpalimy to
będziemy mieli dość ciekawy efekt jak widzimy doszliśmy do tego miejsca
tak the end of main executor service jest wyłączony
w tym miejscu tak no ale nasz kod się zawiesił tutaj prawda
nie wiemy za bardzo co się dzieje tak tutaj widocznie coś z tym transportem
jest nie tak możemy z poziomu idei zrobić sobie coś takiego tutaj
jest taki powiedzmy ikonka takiego aparatu i wykorzystując
to coś możemy coś zrobić tak zwany thread dump thread dump
to jest zrzut wszystkich wątków które są na danym jvm i
tutaj w tym thread dumpie jest pokazane gdzie poszczególne wątki się zatrzymały
czy gdzie były w momencie robienia tego thread dump'a jak
sobie zjedziemy na sam dół mam taką ciekawą sekcję tutaj
jvm nam krzyknął o czymś takim że znalazł jeden deadlock no
i właśnie ten deadlock jest bohaterem dzisiejszego odcinka i o co w nim chodzi zasadniczo
deadlock to jest sytuacja w której mamy przynajmniej dwa wątki jeden
z tych wątków czeka na coś na jakiś obiekt na przykład na którym jest założony
monitor lock monitora który został założony przez drugi wątek
tak czyli powiedzmy na przykład thread jeden czeka na coś co
trzyma thread dwa a za to thread dwa czeka na coś co zlockował thread
jeden tak czyli powiedzmy mamy taką cykliczną zależność tak i teraz żaden
ci się nie ruszy bo czeka na drugiego tak a drugi na pierwszego to jest właśnie deadlock tutaj
tutaj nawet ładnie jvm właśnie nam to opisał prawda tutaj możemy się doczytać na jakim
obiekcie jakiej klasy i tak dalej i jak jeszcze dokładnie
się przyjrzymy temu dump'owi to nawet nam powie w którym miejscu się
zdockowaliśmy tutaj możemy zobaczyć że ten thread 1 czeka
na metodzie get bricks count on tutaj pokazuje
że on jest tutaj a tak naprawdę czeka na założenie locka na
this tego obiektu tak bo tutaj mamy synchronized prawda możemy też zobaczyć
gdzie drugi thread się zatrzymał on
też się zatrzymało na get bricks count ale to już jest pewnie na innym obiekcie prawda
na tym drugim okej teraz zobaczymy co tu się tak naprawdę dzieje w tym transport to
transport to przerzuca cegły z jednego obiektu
tak z jednego z jednej hurtowni do drugiej tak ja
mam taką zależność że my przerzucamy z jedynki do dwójki jednocześnie z
dwójki do jedynki więc możemy zobaczyć co tu się dzieje mamy
synchronize tak i teraz do targeta przerzucamy
sobie te cegły wcześnie jeszcze odejmujemy cegły z naszego obiektu
z this'a i dodajemy do drugiego i teraz
w tym miejscu jak do tego miejsca dochodzimy to już mamy założone na
obiekcie this w tym momencie monitor prawda locka tak
jak drugi wątek z ten który obsługuje na przykład
warehouse 2 dochodzi do tego miejsca to już ma na warehouse 2
założony monitor prawda locka i teraz tu jest ten sleep
to jest tylko po to żeby trochę sprowokować tą sytuację no
i dalej jest wywołanie set bricks count
który też jest synchronized on już wymaga locka na
tym drugim obiekcie no i tu się pojawia problem ponieważ lock na tym obiekcie już jest
założony tak jedynka czeka na dwójkę w tym miejscu a
dwójka nie będzie czekała teraz z założonym lockiem na siebie będzie
czekała na zwolnienie locka z targetu tak czyli z
jedynki no i tu się nigdy tego nie dojdzie w tym miejscu tak no
okej dobra czyli wiemy że mamy locka wiemy mniej więcej z czego
to wynika teraz spróbujmy to naprawić w jaki sposób możemy
zdjąć na przykład tego synchronize stąd no i teraz jak go usunęliśmy to co prawda deadlock
nam zniknie no ale mamy znowu race condition tak czyli powiedzmy z deszczu
pod rynnę tak ten deadlock nawet jest małe prawdopodobieństwo że on się wydarzy
ponieważ może mieć dużo tych warehouse'ów tak na sytuację
kiedy ona akurat symetrycznie do siebie coś przysyłają może być rzadka
no okej czyli teraz powiedzmy możemy mieć niespójny stan w tym
bricks count no okej pójdźmy kawałek dalej żeby zobaczyć czy
możemy coś innego jeszcze zmienić możemy wykorzystać atomic longa no
i teraz mamy coś co wygląda trochę bezpieczniej ale ciągle nie jest bezpieczne z
tym czymś są dwa problemy co prawda tutaj każda z tych linijek tutaj
jest atomowa prawda tutaj odejmowanie
i dodawanie jest atomowe w obrębie atomic longa pierwszy problem
taki że w momencie kiedy odejmujemy te elementy z pierwszego z
pierwszej hurtowni i zanim dodamy je do drugiej tutaj
mi jest jakiś kwant czasu pomiędzy w który może się wbić jakiś inny
obiekt na przykład w tym momencie odczytać stan któregoś z tych pól no
i jakby tutaj porównać to gdzieś w tej po drodze będzie brakowało cegieł
w tym momencie tak bo tutaj zdążyliśmy odjąć tak a tutaj nie dodaliśmy
więc tyle będzie w sumie brakowało czyli mamy taki niespójny stan w momencie kiedy ta
metoda jest wywoływana tak pomiędzy no tak jakby co prawda na początku
i na końcu jest spójny tak ale pamiętajmy że jesteśmy we współbieżnym
świecie w tym momencie drugim problemem jest to że gdybyśmy tutaj na przykład chcieli
zaprząc jakąś logikę która by jeszcze sprawdziła czy ta liczba
tych cegieł nie jest mniejsza niż zero czy jakakolwiek inna biznesowa
logika no to teraz już ciężko jest poruszać się w obrębie tej
atomowości i tego atomic longa tak okej w tym momencie pewnie
byśmy pragnęli żeby jednak ta metoda była zsynchronizowana no
ale mimo wszystko wtedy wpadamy w tego locka tak jest jakieś niskie prawdopodobieństwo że
go dostaniemy na szczęście da się to ominąć pewnym patternem teraz jak cofniemy
się do tego początkowego kodu tak z tym synchronized i
chwilę się zastanowimy zasadniczo ten problem który tutaj mamy wynika
z tego że każdy każde wywołanie tego transportu wewnątrz używa
dwóch locków tak z wyjściowego powiedzmy z wyjściowej
hurtowni i z docelowej hurtowni problem polega na tym że on wywołuje
te locki w odwrotnej kolejności tak tutaj była ta zbieżność że one
na raz do siebie wysyłały te cegły tak no i sztuczka
polega na tym że możemy te locki posortować na przykład tak
przypominam że możemy robić synchronized na przykład na jakimś konkretnym obiekcie
tutaj robimy tylko na takiej metodzie robimy synchronized
niejawnie na obiekcie this tak czyli tak naprawdę na
obiekcie bricks warehouse okej spróbujmy coś takiego zaimplementować
może to wyglądać w ten sposób tak tutaj tworzę
jakąś listę tych locków biorę tutaj wrzucam this wrzucam
target warehouse no i później robi sortowanie
no i następnie sortuje te obiekty tutaj wykorzystuje
sortowanie i sortuje po hash code z tego względu że hash code
po prostu jest bricked warehouse i on nie bazuje w tym momencie na niczym
co jest z tym obiekcie tak więc ten hashcode się nam
nie zmieni prawda więc on jest powiedzmy możemy stabilnie to posortować teraz
i okej teraz ja biorę sobie pierwszy element z
tej listy nie wiem który to jest wiem w każdym razie że on jest stabilnie
jakiś posortowany to się nie będzie zmieniało jak on jest względem innych tak
i na tym obiekcie robi locka tak robię synchronize czyli zakładam
lock na tym monitorze okej później biorę sobie drugi element i
na nim też zakładam no i później mam kawałek tej swojej logiki tutaj
już zakładając że nie korzystam z żadnych dodatkowych locków mam
pewność że tutaj nie będzie żadnego powiedzmy deadlock'a przypominam że jeżeli
w tym miejscu na przykład robimy set bricks count i set bricks count co prawda
jest synchronized to my już w którymś z tych powiedzmy synchronized
mieliśmy zrobionego locka na this tak czyli
jak tu jesteśmy w środku to już na pewno mamy tak jak dostęp tak okej
czyli tu już nie ma szans żebyśmy się blokowali tutaj tak samo ponieważ target
warehouse w którym z tych miejsc też już został zalockowany prawda okej
no i później wychodząc stąd my zwracamy powiedzmy
te locki w odwrotnej kolejności to jest też ważne prawda okej
i z taką implementacją transport to mamy gwarancję
że jeżeli robimy przesył z jedynki do dwójki czy z dwójki do jedynki
to one nam się nie zakleszczą w ten sposób że jedynka czeka na dwójkę a dwójka
na jedynkę tak bo zawsze nie wiemy który ale zawsze one
będą zakładane w tej samej kolejności locki na tych obiektach prawda no
jest to taka ciekawa sztuczka dość okej to wszystko co chciałem
ci pokazać w tej lekcji i w kolejnej już zajmiemy się implementacją jakiegoś projektu dzięki
wielkie i do usłyszenia