JavaRush /Blog Java /Random-PL /Przerwa kawowa #113. 5 rzeczy, których prawdopodobnie nie...

Przerwa kawowa #113. 5 rzeczy, których prawdopodobnie nie wiedziałeś o wielowątkowości w Javie 10 rozszerzeń JetBrains do walki z długiem technicznym

Opublikowano w grupie Random-PL

5 rzeczy, których prawdopodobnie nie wiedziałeś o wielowątkowości w Javie

Źródło: DZone Thread jest sercem języka programowania Java. Nawet uruchomienie programu Hello World wymaga głównego wątku. Jeśli zajdzie taka potrzeba, możemy dodać do programu kolejne wątki, jeśli chcemy, aby kod naszej aplikacji był bardziej funkcjonalny i wydajny. Jeśli mówimy o serwerze WWW, to jednocześnie przetwarza on setki żądań jednocześnie. Używa się do tego wielu wątków. Przerwa kawowa #113.  5 rzeczy, których prawdopodobnie nie wiedziałeś o wielowątkowości w Javie  10 rozszerzeń JetBrains w celu zwalczania zadłużenia technicznego – 1Wątki są niewątpliwie przydatne, jednak praca z nimi może być trudna dla wielu programistów. W tym artykule podzielę się pięcioma koncepcjami wielowątkowości, o których nowi i doświadczeni programiści mogą nie wiedzieć.

1. Kolejność programów i kolejność wykonywania nie są zgodne

Kiedy piszemy kod, zakładamy, że zostanie on wykonany dokładnie tak, jak go napiszemy. Jednak w rzeczywistości tak nie jest. Kompilator Java może zmienić kolejność wykonywania, aby go zoptymalizować, jeśli ustali, że dane wyjściowe nie zmienią się w kodzie jednowątkowym. Spójrz na następujący fragment kodu:
package ca.bazlur.playground;

import java.util.concurrent.Phaser;

public class ExecutionOrderDemo {
    private static class A {
        int x = 0;
    }

    private static final A sharedData1 = new A();
    private static final A sharedData2 = new A();

    public static void main(String[] args) {
        var phaser = new Phaser(3);
        var t1 = new Thread(() -> {
            phaser.arriveAndAwaitAdvance();
            var l1 = sharedData1;
            var l2 = l1.x;
            var l3 = sharedData2;
            var l4 = l3.x;
            var l5 = l1.x;
            System.out.println("Thread 1: " + l2 + "," + l4 + "," + l5);
        });
        var t2 = new Thread(() -> {
            phaser.arriveAndAwaitAdvance();
            var l6 = sharedData1;
            l6.x = 3;
            System.out.println("Thread 2: " + l6.x);
        });
        t1.start();
        t2.start();
        phaser.arriveAndDeregister();
    }
}
Ten kod wydaje się prosty. Mamy dwie udostępnione instancje danych ( sharedData1 isharedData2 ), które korzystają z dwóch wątków. Kiedy wykonujemy kod, oczekujemy, że wynik będzie wyglądał następująco:
Wątek 2: 3 Wątek 1: 0,0,0
Ale jeśli uruchomisz kod kilka razy, zobaczysz inny wynik:
Wątek 2: 3 Wątek 1: 3,0,3 Wątek 2: 3 Wątek 1: 0,0,3 Wątek 2: 3 Wątek 1: 3,3,3 Wątek 2: 3 Wątek 1: 0,3,0 Wątek 2 : 3 Wątek 1: 0,3,3
Nie twierdzę, że wszystkie te strumienie będą odtwarzane dokładnie tak samo na Twoim komputerze, ale jest to całkowicie możliwe.

2. Liczba wątków Java jest ograniczona

Tworzenie wątku w Javie jest łatwe. Nie oznacza to jednak, że możemy stworzyć ich tyle, ile nam się podoba. Liczba wątków jest ograniczona. Ile wątków możemy utworzyć na konkretnej maszynie, łatwo sprawdzimy za pomocą następującego programu:
package ca.bazlur.playground;

import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

public class Playground {
    public static void main(String[] args) {
        var counter = new AtomicInteger();
        while (true) {
            new Thread(() -> {
                int count = counter.incrementAndGet();
                System.out.println("thread count = " + count);
                LockSupport.park();
            }).start();
        }
    }
}
Powyższy program jest bardzo prosty. Tworzy wątek w pętli, a następnie go parkuje, co oznacza, że ​​wątek jest wyłączony do wykorzystania w przyszłości, ale wykonuje wywołanie systemowe i przydziela pamięć. Program kontynuuje tworzenie wątków, dopóki nie będzie mógł ich utworzyć więcej, a następnie zgłasza wyjątek. Interesuje nas liczba, którą otrzymamy do czasu, aż program zgłosi wyjątek. Na moim komputerze udało mi się utworzyć tylko 4065 wątków.

3. Zbyt wiele wątków nie gwarantuje lepszej wydajności

Naiwnością jest wierzyć, że ułatwienie wątków w Javie poprawi wydajność aplikacji. Niestety, to założenie jest błędne w przypadku naszego tradycyjnego modelu wielowątkowości dostępnego obecnie w Javie. W rzeczywistości zbyt wiele wątków może zmniejszyć wydajność aplikacji. Najpierw zadajmy sobie pytanie: jaka jest optymalna maksymalna liczba wątków, jaką możemy utworzyć, aby zmaksymalizować wydajność aplikacji? Cóż, odpowiedź nie jest taka prosta. Bardzo dużo zależy od rodzaju pracy jaką wykonujemy. Jeśli mamy wiele niezależnych zadań, z których wszystkie mają charakter obliczeniowy i nie blokują żadnych zasobów zewnętrznych, wówczas posiadanie dużej liczby wątków nie poprawi znacząco wydajności. Z drugiej strony, jeśli mamy procesor 8-rdzeniowy, optymalna liczba wątków mogłaby wynosić (8 + 1). W takim przypadku możemy polegać na wątku równoległym wprowadzonym w Javie 8. Domyślnie wątek równoległy korzysta ze współdzielonej puli Fork/Join. Tworzy wątki równe liczbie dostępnych procesorów, co wystarcza do ich intensywnej pracy. Dodanie większej liczby wątków do zadania intensywnie obciążającego procesor, w którym nic nie jest zablokowane, nie poprawi wydajności. Raczej po prostu zmarnujemy zasoby. Notatka. Powodem posiadania dodatkowego wątku jest to, że nawet wątek wymagający dużej mocy obliczeniowej czasami powoduje błąd strony lub jest zawieszany z innego powodu. (Zobacz: Równoległość Java w praktyce , Brian Goetz, strona 170). Załóżmy jednak na przykład, że zadania są powiązane z wejściami/wyjściami. W tym przypadku zależą one od komunikacji zewnętrznej (np. baza danych, inne API), więc większa liczba wątków ma sens. Powodem jest to, że gdy wątek oczekuje na interfejs API Rest, inne wątki mogą kontynuować pracę. Teraz możemy ponownie zapytać, ile wątków to za dużo dla takiego przypadku? Zależy. Nie ma liczb doskonałych, które pasowałyby do wszystkich przypadków. Dlatego musimy przeprowadzić odpowiednie testy, aby dowiedzieć się, co najlepiej sprawdza się w przypadku naszego konkretnego obciążenia pracą i zastosowania. W najbardziej typowym scenariuszu mamy zazwyczaj mieszany zestaw zadań. I w takich przypadkach sprawy dobiegają końca. W swojej książce „Java Concurrency in Practice” Brian Goetz zaproponował formułę, którą możemy zastosować w większości przypadków. Liczba wątków = liczba dostępnych rdzeni * (1 + czas oczekiwania / czas obsługi) Czas oczekiwania może wynosić I/O, na przykład oczekiwanie na odpowiedź HTTP, uzyskanie blokady i tak dalej. Czas naprawy(Czas usługi) to czas obliczeń, na przykład przetwarzania odpowiedzi HTTP, organizowania/unmarshalingu i tak dalej. Na przykład aplikacja wywołuje interfejs API, a następnie go przetwarza. Jeśli mamy 8 procesorów na serwerze aplikacji, średni czas odpowiedzi API wynosi 100ms, a czas przetwarzania odpowiedzi 20ms, to idealny rozmiar wątku byłby następujący:
N = 8 * ( 1 + 100/20) = 48
Jest to jednak nadmierne uproszczenie; odpowiednie testy mają zawsze kluczowe znaczenie dla określenia liczby.

4. Wielowątkowość nie jest równoległością

Czasami używamy zamiennie wielowątkowości i równoległości, ale nie jest to już całkowicie istotne. Chociaż w Javie osiągamy jedno i drugie za pomocą wątku, są to dwie różne rzeczy. „W programowaniu wielowątkowość jest przypadkiem szczególnym niezależnie od uruchomionych procesów, a równoległość to jednoczesne wykonywanie (ewentualnie powiązanych) obliczeń. Wielowątkowość polega na interakcji z wieloma rzeczami jednocześnie. Współbieżność umożliwia robienie wielu rzeczy jednocześnie.” Powyższa definicja podana przez Roba Pike'a jest dość dokładna. Załóżmy, że mamy całkowicie niezależne zadania i można je obliczyć osobno. W tym przypadku zadania te nazywane są równoległymi i można je wykonać za pomocą puli Fork/Join lub wątku równoległego. Z drugiej strony, jeśli mamy wiele zadań, niektóre z nich mogą zależeć od innych. Sposób, w jaki komponujemy i tworzymy strukturę, nazywamy wielowątkowością. Ma to związek ze strukturą. Możemy chcieć wykonać kilka zadań jednocześnie, aby osiągnąć określony wynik, niekoniecznie szybciej kończąc jedno.

5. Project Loom pozwala nam tworzyć miliony wątków

W poprzednim punkcie argumentowałem, że posiadanie większej liczby wątków nie oznacza poprawy wydajności aplikacji. Jednak w dobie mikroserwisów wchodzimy w interakcję ze zbyt wieloma usługami, aby wykonać jakąkolwiek konkretną pracę. W takim scenariuszu wątki przez większość czasu pozostają w stanie zablokowanym. O ile nowoczesny system operacyjny jest w stanie obsłużyć miliony otwartych gniazd, o tyle nie możemy otworzyć wielu kanałów komunikacyjnych, gdyż ogranicza nas liczba wątków. A co jeśli utworzysz miliony wątków, a każdy z nich będzie korzystał z otwartego gniazda do komunikacji ze światem zewnętrznym? Zdecydowanie poprawi to przepustowość naszej aplikacji. Aby wesprzeć ten pomysł, istnieje inicjatywa w Javie o nazwie Project Loom. Za jego pomocą możemy stworzyć miliony wirtualnych wątków. Na przykład, korzystając z poniższego fragmentu kodu, udało mi się utworzyć 4,5 miliona wątków na moim komputerze.
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;

public class Main {
    public static void main(String[] args) {
        var counter = new AtomicInteger();

        // 4_576_279
        while (true) {
            Thread.startVirtualThread(() -> {
                int count = counter.incrementAndGet();
                System.out.println("thread count = " + count);
                LockSupport.park();
            });
        }
    }
}
Aby uruchomić ten program, musisz mieć zainstalowaną Javę 18, którą możesz pobrać tutaj . Możesz uruchomić kod za pomocą następującego polecenia: java --source 18 --enable-preview Main.java

10 rozszerzeń JetBrains do walki z długiem technicznym

Źródło: DZone Wiele zespołów programistycznych odczuwa ogromną presję dotrzymywania terminów. Z tego powodu często nie mają wystarczająco dużo czasu na naprawienie i oczyszczenie bazy kodu. Czasami w takich sytuacjach dług techniczny szybko się kumuluje. Rozszerzenia edytora mogą pomóc rozwiązać ten problem. Rzućmy okiem na 10 najlepszych rozszerzeń JetBrains do walki z długiem technicznym (ze wsparciem Java). Przerwa kawowa #113.  5 rzeczy, których prawdopodobnie nie wiedziałeś o wielowątkowości w Javie  10 rozszerzeń JetBrains do walki z długiem technicznym – 2

Narzędzia refaktoryzacji i długu technicznego

1. Refaktoryzacja

RefactorInsight poprawia widoczność zmian w kodzie w IDE, dostarczając informacji o refaktoryzacji.
  1. Rozszerzenie definiuje refaktoryzację w żądaniach scalania.
  2. Oznacza zatwierdzenia zawierające refaktoryzację.
  3. Pomaga w przeglądaniu refaktoryzacji dowolnego konkretnego zatwierdzenia wybranego na karcie Git Log.
  4. Pokazuje historię refaktoryzacji klas, metod i pól.

2. Krokowe śledzenie problemów w IDE

Stepsize to świetne narzędzie do śledzenia problemów dla programistów. Rozszerzenie pomaga inżynierom nie tylko tworzyć lepsze TODO i komentarze do kodu, ale także ustalać priorytety długu technicznego, refaktoryzacji i tym podobnych:
  1. Stepsize umożliwia tworzenie i przeglądanie zadań w kodzie bezpośrednio w edytorze.
  2. Znajdź problemy wpływające na funkcje, nad którymi pracujesz.
  3. Dodawaj problemy do swoich sprintów, korzystając z integracji Jira, Asana, Linear, Azure DevOps i GitHub.

3. Nowy strumień kodu reliktu

New Relic CodeStream to platforma współpracy z programistami, służąca do omawiania i przeglądania kodu. Obsługuje żądania ściągnięcia z GitHub, BitBucket i GitLab, zarządzanie problemami z Jira, Trello, Asana i 9 innych, a także zapewnia dyskusje na temat kodu, łącząc to wszystko w całość.
  1. Twórz, przeglądaj i łącz żądania ściągnięcia w GitHub.
  2. Uzyskaj informacje zwrotne na temat prac w toku dzięki wstępnym przeglądom kodu.
  3. Omawianie problemów z kodem z członkami zespołu.

DO ZROBIENIA i komentarze

4. Zakreślacz komentarzy

Ta wtyczka umożliwia tworzenie niestandardowego podświetlania linii komentarzy i słów kluczowych języka. Wtyczka ma również możliwość definiowania niestandardowych tokenów do podświetlania linii komentarzy.

5. Lepsze komentarze

Rozszerzenie Better Comments pomaga tworzyć jaśniejsze komentarze w kodzie. Dzięki temu rozszerzeniu będziesz mógł klasyfikować swoje adnotacje na:
  1. Alerty.
  2. Upraszanie.
  3. DO ZROBIENIA.
  4. Podstawowe momenty.

Błędy i luki w zabezpieczeniach

6.SonarLint _

SonarLint umożliwia rozwiązywanie problemów z kodem, zanim one powstaną. Może być również używany jako moduł sprawdzania pisowni. SonarLint podkreśla błędy i luki w zabezpieczeniach podczas pisania kodu, wyświetlając jasne instrukcje dotyczące ich naprawiania, dzięki czemu można je naprawić przed zatwierdzeniem kodu.

7. SpotBug

Wtyczka SpotBugs zapewnia statyczną analizę kodu bajtowego w celu znalezienia błędów w kodzie Java z IntelliJ IDEA. SpotBugs to narzędzie do wykrywania defektów w języku Java, które wykorzystuje analizę statyczną do wyszukiwania ponad 400 wzorców błędów, takich jak dereferencje wskaźników zerowych, nieskończone pętle rekurencyjne, niewłaściwe użycie bibliotek Java i zakleszczenia. SpotBugs potrafi zidentyfikować setki poważnych defektów w dużych aplikacjach (zazwyczaj około 1 defektu na 1000-2000 linii surowych, nieskomentowanych instrukcji).

8. Skaner podatności Snyk

Skaner Vulnerability Scanner firmy Snyk pomaga znaleźć i naprawić luki w zabezpieczeniach oraz problemy z jakością kodu w Twoich projektach.
  1. Znajdowanie i naprawianie problemów związanych z bezpieczeństwem.
  2. Zobacz listę różnych typów problemów, podzieloną na kategorie.
  3. Wyświetla wskazówki dotyczące rozwiązywania problemów.

9. Lokalizator znaków o zerowej szerokości

Ta wtyczka usprawnia sprawdzanie i wykrywanie trudnych do znalezienia błędów związanych z niewidocznymi znakami o zerowej szerokości w kodzie źródłowym i zasobach. Podczas korzystania upewnij się, że zaznaczono opcję „Znak Unicode o zerowej szerokości”.

10.KodMR _

CodeMR to narzędzie do analizy jakości oprogramowania i kodu statycznego, które pomaga producentom oprogramowania opracowywać lepszy kod i programy. CodeMR wizualizuje metryki kodu i atrybuty jakości wysokiego poziomu (sprzężenie, złożoność, spójność i rozmiar) w różnych widokach, takich jak struktura pakietu, TreeMap, Sunburst, zależność i widoki wykresów.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION