Java Academy · Oppitunti

Alusta- ja virtuaalisäikeet

Milloin kumpaakin kannattaa käyttää.

Oppitunti 3/413 vaihetta

Alusta- ja virtuaalisäikeet on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.

Kaksi säietyyppiä

Javassa on nyt kaksi säietyyppiä. Alustasäikeet ovat perinteisiä käyttöjärjestelmäsäikeiden kääreitä. Virtuaalisäikeet ovat kevyitä ja JVM:n hallinnoimia.

Sen tietäminen, milloin kumpaakin kannattaa käyttää, on skaalautuvan samanaikaisen Java-koodin ydin.

Alustasäikeen luominen

Alustasäie luodaan kutsulla Thread.ofPlatform(), joka on Thread.ofVirtual()-metodin vastine.

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread p = Thread.ofPlatform().name("native-worker").start(() ->
            System.out.println("Platform? " + !Thread.currentThread().isVirtual()));
        p.join();
    }
}

Kustannusten vertailu

Alustasäikeet ovat raskaita:

  • Niille varataan noin 1 Mt pinoa kutakin säiettä kohden
  • Niiden luominen on hidasta
  • Niitä voidaan luoda vain muutamia tuhansia

Virtuaalisäikeet ovat edullisia: niiden aloituspino on pieni, ne luodaan nopeasti ja niitä voidaan luoda miljoonia.

I/O-sidonnainen työ

Jos tehtävä käyttää suurimman osan ajastaan verkon, levyn tai tietokannan odottamiseen, virtuaalisäikeet ovat selvästi parempi vaihtoehto.

Kun yksi virtuaalisäie estyy, sen kantajasäie vapautuu muiden suorittamiseen, joten muutama käyttöjärjestelmäsäie voi palvella tuhansia pyyntöjä.

CPU-sidonnainen työ

Puhtaassa laskennassa, joka ei koskaan esty, virtuaalisäikeet eivät nopeuta suoritusta. Suorituskykyä rajoittaa ytimien määrä.

Tässä tilanteessa prosessorien määrän mukaan mitoitettu kiinteä pooli on oikea työkalu.

import java.util.concurrent.*;

public class Main {
    public static void main(String[] args) throws Exception {
        int cores = Runtime.getRuntime().availableProcessors();
        try (ExecutorService cpu = Executors.newFixedThreadPool(cores)) {
            Future<Long> f = cpu.submit(() -> {
                long s = 0;
                for (long i = 0; i < 1_000_000L; i++) s += i;
                return s;
            });
            System.out.println("Cores: " + cores + ", sum: " + f.get());
        }
    }
}

Estymisen simulointi

Tämä koodikatkelma näyttää useiden virtuaalisäikeiden nukkuvan samanaikaisesti. Nukkuminen toimii tässä estyvän I/O:n vastineena. Kuvitelkaa, että 10 000 alustasäiettä tekisi saman.

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {
    public static void main(String[] args) {
        AtomicInteger done = new AtomicInteger();
        try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
            for (int i = 0; i < 10_000; i++) {
                exec.submit(() -> {
                    try { Thread.sleep(50); } catch (InterruptedException e) {}
                    done.incrementAndGet();
                });
            }
        }
        System.out.println("Finished blocking tasks: " + done.get());
    }
}

Daemon-tila

Virtuaalisäikeet ovat aina daemon-säikeitä, eikä niitä voi muuttaa muiksi kuin daemon-säikeiksi. Alustasäikeet perivät oletusarvoisesti luojansa daemon-tilan, mutta niiden tila voidaan määrittää erikseen.

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread v = Thread.ofVirtual().unstarted(() -> {});
        Thread p = Thread.ofPlatform().unstarted(() -> {});
        System.out.println("virtual daemon: " + v.isDaemon());
        System.out.println("platform daemon: " + p.isDaemon());
    }
}

Prioriteetit ohitetaan

Virtuaalisäikeet ilmoittavat aina prioriteetikseen NORM_PRIORITY, eikä prioriteetin asettamisella ole vaikutusta. Ajoituksesta huolehtii JVM, ei käyttöjärjestelmän ajoitin.

public class Main {
    public static void main(String[] args) {
        Thread v = Thread.ofVirtual().unstarted(() -> {});
        v.setPriority(Thread.MAX_PRIORITY);
        System.out.println("Priority is still: " + v.getPriority());
    }
}

Valintaohje

Käytännön nyrkkisääntö:

  • Paljon I/O:n odottamiseen jääviä tehtäviä? Käyttäkää virtuaalisäikeitä.
  • Suorittimen rajoittamaa raskasta laskentaa? Käyttäkää kiinteää alustasäikeiden poolia.
  • Tarvitsetteko käyttöjärjestelmätason säikeiden hienosäätöä, kuten prioriteetin tai affiniteetin määrittämistä? Käyttäkää alustasäikeitä.

Ne toimivat rinnakkain

Teidän ei tarvitse valita yhtä vaihtoehtoa koko ohjelmaa varten. Tyypillisessä sovelluksessa virtuaalisäikeitä käytetään pyyntöjen käsittelyyn ja pientä alustasäikeiden poolia suoritinta kuormittaviin osioihin.

Molemmissa käytetään samaa Thread-rajapintaa, joten niiden yhdistäminen on saumatonta.

Vinkki siirtymiseen

Kun siirrätte I/O-raskasta palvelua virtuaalisäikeisiin, pienin muutos on executorin vaihtaminen: korvatkaa kiinteä tai välimuistia käyttävä pooli kutsulla newVirtualThreadPerTaskExecutor().

Varokaa kuitenkin pinningiä ja ThreadLocalien väärinkäyttöä, joita käsitellään seuraavalla oppitunnilla.

Pikatarkistus

Valitkaa kuormitus, jossa virtuaalisäikeistä on selvimmin hyötyä.

Kertaus

Vertailitte kahta säiemallia:

  • Alustasäikeet: raskaita ja käyttöjärjestelmän tukemia, sopivat parhaiten CPU-sidonnaiseen työhön ja käyttöjärjestelmätason säätöön
  • Virtuaalisäikeet: edullisia ja JVM:n hallinnoimia, aina daemon-säikeitä, sopivat parhaiten I/O-sidonnaiseen samanaikaisuuteen
  • Ne toimivat rinnakkain ja käyttävät samaa APIa

Seuraavaksi käsitellään pinningiä ja ThreadLocaleja.

Aloita maksutta

Opi Java tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
104
Oppitunnit
374

Usein kysytyt kysymykset

Onko oppitunti ”Alusta- ja virtuaalisäikeet” ilmainen?

Kyllä – oppitunnin ”Alusta- ja virtuaalisäikeet” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Alusta- ja virtuaalisäikeet”?

Milloin kumpaakin kannattaa käyttää. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”Alusta- ja virtuaalisäikeet”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?

Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Mitä virtuaalisäikeet ovat
  2. Virtuaalisäikeiden luonti
  3. Alusta- ja virtuaalisäikeet
  4. Sudenkuopat: pinning ja ThreadLocalit
← Takaisin: Java Academy