JavaRush /Java Blog /Random-TL /Coffee break #113. 5 bagay na malamang na hindi mo alam t...

Coffee break #113. 5 bagay na malamang na hindi mo alam tungkol sa multithreading sa Java. 10 JetBrains Extension para Labanan ang Teknikal na Utang

Nai-publish sa grupo

5 Mga Bagay na Malamang na Hindi Mo Alam Tungkol sa Multithreading sa Java

Source: DZone Thread ay ang puso ng Java programming language. Kahit na ang pagpapatakbo ng programang Hello World ay nangangailangan ng pangunahing thread. Kung kinakailangan, maaari kaming magdagdag ng iba pang mga thread sa program kung gusto naming maging mas functional at gumaganap ang aming application code. Kung pinag-uusapan natin ang tungkol sa isang web server, pagkatapos ay sabay-sabay itong nagpoproseso ng daan-daang mga kahilingan nang sabay-sabay. Maramihang mga thread ang ginagamit para dito. Coffee break #113.  5 bagay na malamang na hindi mo alam tungkol sa multithreading sa Java.  10 JetBrains Extension para Labanan ang Teknikal na Utang - 1Ang mga thread ay walang alinlangan na kapaki-pakinabang, ngunit ang pagtatrabaho sa kanila ay maaaring maging mahirap para sa maraming mga developer. Sa artikulong ito, ibabahagi ko ang limang konsepto ng multithreading na maaaring hindi alam ng mga bago at may karanasang developer.

1. Ang pagkakasunud-sunod ng programa at pagkakasunud-sunod ng pagpapatupad ay hindi magkatugma

Kapag nagsusulat kami ng code, ipinapalagay namin na ito ay isasagawa nang eksakto sa paraan ng pagsulat namin nito. Gayunpaman, sa katotohanan ay hindi ito ang kaso. Maaaring baguhin ng Java compiler ang pagkakasunud-sunod ng pagpapatupad upang ma-optimize ito kung matutukoy nito na hindi magbabago ang output sa single-threaded code. Tingnan ang sumusunod na snippet ng code:
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();
    }
}
Mukhang simple ang code na ito. Mayroon kaming dalawang shared data instance ( sharedData1 at sharedData2 ) na gumagamit ng dalawang thread. Kapag pinaandar namin ang code, inaasahan namin na ang output ay magiging ganito:
Thread 2: 3 Thread 1: 0,0,0
Ngunit kung patakbuhin mo ang code nang maraming beses, makakakita ka ng ibang resulta:
Thread 2: 3 Thread 1: 3,0,3 Thread 2: 3 Thread 1: 0,0,3 Thread 2: 3 Thread 1: 3,3,3 Thread 2: 3 Thread 1: 0,3,0 Thread 2 : 3 Thread 1: 0,3,3
Hindi ko sinasabi na ang lahat ng mga stream na ito ay gaganap nang eksakto tulad nito sa iyong makina, ngunit ito ay ganap na posible.

2. Limitado ang bilang ng mga thread ng Java

Ang paglikha ng isang thread sa Java ay madali. Gayunpaman, hindi ito nangangahulugan na maaari tayong lumikha ng marami sa kanila hangga't gusto natin. Limitado ang bilang ng mga thread. Madali nating malalaman kung gaano karaming mga thread ang magagawa natin sa isang partikular na makina gamit ang sumusunod na programa:
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();
        }
    }
}
Ang programa sa itaas ay napaka-simple. Lumilikha ito ng isang thread sa isang loop at pagkatapos ay ipinarada ito, na nangangahulugang ang thread ay hindi pinagana para magamit sa hinaharap ngunit nagsasagawa ng isang tawag sa system at naglalaan ng memorya. Ang programa ay patuloy na lumilikha ng mga thread hanggang sa hindi na ito makalikha, at pagkatapos ay magtapon ng isang pagbubukod. Interesado kami sa numerong matatanggap namin hanggang sa maglabas ang programa ng exception. Sa aking computer nakagawa lang ako ng 4065 na mga thread.

3. Masyadong maraming mga thread ay hindi ginagarantiya ng mas mahusay na pagganap

Ito ay walang muwang na maniwala na ang pagpapadali ng mga thread sa Java ay magpapabuti sa pagganap ng application. Sa kasamaang palad, mali ang pagpapalagay na ito sa aming tradisyonal na multithreading na modelo na ibinibigay ngayon ng Java. Sa katunayan, ang masyadong maraming mga thread ay maaaring mabawasan ang pagganap ng isang application. Itanong muna natin ang tanong na ito: ano ang pinakamainam na maximum na bilang ng mga thread na maaari nating gawin upang ma-maximize ang pagganap ng application? Well, hindi ganoon kadali ang sagot. Nakadepende ito sa uri ng trabahong ginagawa natin. Kung mayroon kaming maraming independiyenteng mga gawain, na lahat ay computational at hindi hinaharangan ang anumang panlabas na mapagkukunan, kung gayon ang pagkakaroon ng isang malaking bilang ng mga thread ay hindi mapapabuti ang pagganap. Sa kabilang banda, kung mayroon kaming 8-core na processor, ang pinakamainam na bilang ng mga thread ay maaaring (8 + 1). Sa ganoong sitwasyon, maaari tayong umasa sa parallel thread na ipinakilala sa Java 8. Bilang default, ginagamit ng parallel thread ang shared Fork/Join pool. Lumilikha ito ng mga thread na katumbas ng bilang ng magagamit na mga processor, na sapat para sa kanila na gumana nang masinsinan. Ang pagdaragdag ng higit pang mga thread sa isang CPU-intensive na trabaho kung saan walang naka-block ay hindi magpapahusay sa performance. Sa halip, magsasayang lang tayo ng mga mapagkukunan. Tandaan. Ang dahilan ng pagkakaroon ng dagdag na thread ay kahit na ang isang compute-intensive na thread kung minsan ay nagdudulot ng page fault o nasuspinde sa ibang dahilan. (Tingnan ang: Java Parallelism in Practice , Brian Goetz, pahina 170) Gayunpaman, ipagpalagay, halimbawa, na ang mga gawain ay I/O bound. Sa kasong ito, umaasa sila sa panlabas na komunikasyon (hal. database, iba pang mga API), kaya ang mas malaking bilang ng mga thread ay may katuturan. Ang dahilan ay kapag ang isang thread ay naghihintay sa Rest API, ang ibang mga thread ay maaaring magpatuloy sa paggana. Ngayon ay maaari nating itanong muli, gaano karaming mga thread ang masyadong marami para sa naturang kaso? Depende. Walang perpektong numero na akma sa lahat ng kaso. Samakatuwid, dapat tayong gumawa ng sapat na pagsubok upang malaman kung ano ang pinakamahusay para sa ating partikular na workload at aplikasyon. Sa pinakakaraniwang senaryo, kadalasan ay mayroon kaming magkakahalong hanay ng mga gawain. At sa ganitong mga kaso ang mga bagay ay matatapos. Sa kanyang aklat na "Java Concurrency in Practice," iminungkahi ni Brian Goetz ang isang formula na magagamit natin sa karamihan ng mga kaso. Bilang ng mga thread = Bilang ng Mga Magagamit na Core * (1 + Oras ng paghihintay / Oras ng serbisyo) Ang oras ng paghihintay ay maaaring IO, tulad ng paghihintay ng tugon ng HTTP, pagkuha ng lock, at iba pa. Oras ng Serbisyo(Service time) ay ang oras ng pag-compute, gaya ng pagpoproseso ng HTTP response, marshaling/unmarshaling, at iba pa. Halimbawa, ang isang application ay tumatawag sa isang API at pagkatapos ay pinoproseso ito. Kung mayroon kaming 8 processor sa application server, ang average na oras ng pagtugon ng API ay 100ms, at ang oras ng pagpoproseso ng tugon ay 20ms, kung gayon ang perpektong laki ng thread ay:
N = 8 * ( 1 + 100/20) = 48
Gayunpaman, ito ay isang sobrang pagpapasimple; ang sapat na pagsubok ay palaging kritikal sa pagtukoy ng numero.

4. Ang multithreading ay hindi parallelism

Minsan ginagamit namin ang multithreading at parallelism nang magkapalit, ngunit hindi na ito ganap na nauugnay. Bagama't sa Java ay nakakamit namin ang parehong gamit ang isang thread, ang mga ito ay dalawang magkaibang bagay. "Sa programming, ang multithreading ay isang espesyal na kaso anuman ang mga prosesong tumatakbo, at ang parallelism ay ang sabay-sabay na pagpapatupad ng (posibleng nauugnay) mga kalkulasyon. Ang multithreading ay tungkol sa pakikipag-ugnayan sa maraming bagay nang sabay-sabay. Ang concurrency ay gumagawa ng maraming bagay nang sabay-sabay.” Ang kahulugan sa itaas na ibinigay ni Rob Pike ay medyo tumpak. Sabihin nating mayroon tayong ganap na independiyenteng mga gawain, at maaari silang kalkulahin nang hiwalay. Sa kasong ito, ang mga gawaing ito ay tinatawag na parallel at maaaring isagawa sa isang Fork/Join pool o isang parallel na thread. Sa kabilang banda, kung marami tayong gawain, ang ilan sa mga ito ay maaaring umasa sa iba. Ang paraan ng ating pagbubuo at istraktura ay tinatawag na multithreading. Ito ay may kinalaman sa istraktura. Maaaring gusto nating magsagawa ng ilang mga gawain nang sabay-sabay upang makamit ang isang tiyak na resulta, nang hindi kinakailangang matapos ang isa nang mas mabilis.

5. Binibigyang-daan kami ng Project Loom na lumikha ng milyun-milyong mga thread

Sa nakaraang punto, nagtalo ako na ang pagkakaroon ng mas maraming mga thread ay hindi nangangahulugang pinabuting pagganap ng application. Gayunpaman, sa panahon ng mga microservice, nakikipag-ugnayan kami sa napakaraming serbisyo para magawa ang anumang partikular na gawain. Sa ganoong sitwasyon, ang mga thread ay nananatili sa isang naka-block na estado sa halos lahat ng oras. Bagama't kayang hawakan ng modernong OS ang milyun-milyong bukas na socket, hindi kami makakapagbukas ng maraming channel ng komunikasyon dahil nalilimitahan kami ng bilang ng mga thread. Ngunit paano kung lumikha ka ng milyun-milyong mga thread, at bawat isa sa kanila ay gumagamit ng isang bukas na socket upang makipag-usap sa labas ng mundo? Ito ay tiyak na mapapabuti ang aming application throughput. Upang suportahan ang ideyang ito, mayroong isang inisyatiba sa Java na tinatawag na Project Loom. Gamit ito, makakagawa tayo ng milyun-milyong virtual na thread. Halimbawa, gamit ang sumusunod na snippet ng code, nakagawa ako ng 4.5 milyong mga thread sa aking makina.
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();
            });
        }
    }
}
Upang patakbuhin ang program na ito dapat ay mayroon kang Java 18 na naka-install, na maaaring ma-download dito . Maaari mong patakbuhin ang code gamit ang sumusunod na command: java --source 18 --enable-preview Main.java

10 JetBrains Extension para Labanan ang Teknikal na Utang

Pinagmulan: DZone Maraming development team ang nakadarama ng matinding pressure upang matugunan ang mga deadline. Dahil dito, madalas silang walang sapat na oras upang ayusin at linisin ang kanilang codebase. Minsan sa mga sitwasyong ito, mabilis na naipon ang teknikal na utang. Makakatulong ang mga extension ng editor na malutas ang problemang ito. Tingnan natin ang 10 pinakamahusay na extension ng JetBrains upang labanan ang teknikal na utang (na may suporta sa Java). Coffee break #113.  5 bagay na malamang na hindi mo alam tungkol sa multithreading sa Java.  10 JetBrains Extension para Labanan ang Teknikal na Utang - 2

Refactoring at teknikal na mga tool sa utang

1. RefactorInsight

Pinapabuti ng RefactorInsight ang visibility ng mga pagbabago sa code sa IDE sa pamamagitan ng pagbibigay ng impormasyon tungkol sa mga refactorings.
  1. Tinutukoy ng extension ang mga refactoring sa mga kahilingan sa pagsasama.
  2. Marks commit na naglalaman ng mga refactorings.
  3. Tumutulong sa pagtingin sa refactoring ng anumang partikular na commit na napili sa tab na Git Log.
  4. Ipinapakita ang kasaysayan ng refactoring ng mga klase, pamamaraan, at field.

2. Stepsize Issue Tracker sa IDE

Ang Stepsize ay isang mahusay na tagasubaybay ng isyu para sa mga developer. Ang extension ay nakakatulong sa mga inhinyero na hindi lamang gumawa ng mas mahuhusay na TODO at mga komento sa code, ngunit bigyang-priyoridad din ang teknikal na utang, refactorings, at mga katulad nito:
  1. Hinahayaan ka ng Stepsize na lumikha at tingnan ang mga gawain sa code sa mismong editor.
  2. Maghanap ng mga isyu na nakakaapekto sa mga feature na iyong ginagawa.
  3. Magdagdag ng mga isyu sa iyong mga sprint gamit ang mga pagsasama ng Jira, Asana, Linear, Azure DevOps, at GitHub.

3. Bagong Relic CodeStream

Ang Bagong Relic CodeStream ay isang platform ng pakikipagtulungan ng developer para sa pagtalakay at pagsusuri ng code. Sinusuportahan nito ang mga pull request mula sa GitHub, BitBucket at GitLab, pamamahala ng isyu mula sa Jira, Trello, Asana at 9 na iba pa, at nagbibigay ng mga talakayan sa code, na pinagsama ang lahat ng ito.
  1. Gumawa, suriin, at pagsamahin ang mga pull request sa GitHub.
  2. Makakuha ng feedback sa kasalukuyang ginagawa gamit ang mga paunang pagsusuri sa code.
  3. Pagtalakay sa mga problema sa code sa mga kasamahan sa koponan.

TODO at mga komento

4. Highlighter ng mga Komento

Binibigyang-daan ka ng plugin na ito na lumikha ng custom na pag-highlight ng mga linya ng komento at mga keyword ng wika. Ang plugin ay mayroon ding kakayahang tumukoy ng mga custom na token para sa pag-highlight ng mga linya ng komento.

5. Mas Mahusay na Mga Komento

Tinutulungan ka ng extension ng Better Comments na lumikha ng mas malinaw na mga komento sa iyong code. Gamit ang extension na ito magagawa mong uriin ang iyong mga anotasyon sa:
  1. Mga alerto.
  2. Mga kahilingan.
  3. GAGAWIN.
  4. Mga pangunahing sandali.

Mga bug at kahinaan sa seguridad

6.SonarLint _

Binibigyang-daan ka ng SonarLint na i-troubleshoot ang mga problema sa code bago sila lumitaw. Maaari din itong gamitin bilang isang spell checker. Itinatampok ng SonarLint ang mga bug at kahinaan sa seguridad habang nagko-code ka, na may malinaw na mga tagubilin sa remediation para maayos mo ang mga ito bago gawin ang code.

7. SpotBugs

Ang SpotBugs plugin ay nagbibigay ng static na bytecode analysis upang mahanap ang mga bug sa Java code mula sa IntelliJ IDEA. Ang SpotBugs ay isang tool sa pagtuklas ng depekto para sa Java na gumagamit ng static na pagsusuri upang makahanap ng higit sa 400 mga pattern ng bug tulad ng mga null pointer dereference, walang katapusang recursive loop, maling paggamit ng mga Java library, at deadlocks. Maaaring tukuyin ng SpotBugs ang daan-daang malalang depekto sa malalaking application (karaniwan ay humigit-kumulang 1 depekto sa bawat 1000-2000 na linya ng mga hilaw na pahayag na walang komento).

8. Snyk Vulnerability Scanner

Tinutulungan ka ng Vulnerability Scanner ng Snyk na mahanap at ayusin ang mga kahinaan sa seguridad at mga isyu sa kalidad ng code sa iyong mga proyekto.
  1. Paghahanap at pag-aayos ng mga problema sa seguridad.
  2. Tingnan ang isang listahan ng iba't ibang uri ng mga problema, na nahahati sa mga kategorya.
  3. Nagpapakita ng mga tip sa pag-troubleshoot.

9. Zero Width Character Locator

Pinapahusay ng plugin na ito ang pagsuri at pagtuklas ng mga error na mahirap hanapin na nauugnay sa mga hindi nakikitang zero width na character sa source code at mga mapagkukunan. Kapag gumagamit, tiyaking naka-enable ang check na "Zero width unicode character."

10. CodeMR _

Ang CodeMR ay isang kalidad ng software at static na tool sa pagsusuri ng code na tumutulong sa mga kumpanya ng software na bumuo ng mas mahusay na code at mga programa. Ang CodeMR ay nagpapakita ng mga sukatan ng code at mataas na antas na mga katangian ng kalidad (pagsasama, pagiging kumplikado, pagkakaisa, at laki) sa iba't ibang view gaya ng Package Structure, TreeMap, Sunburst, Dependency, at Graph Views.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION