window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version: 2, } ;(funktion () { var w = vindue if (w.LeadBooster) { console.warn('LeadBooster findes allerede') } else { w.LeadBooster = { q: [], on: function (n, h) { this.q.push({ t: 'o', n: n, h: h }) }, trigger: function (n) { this.q.push({ t: 't', n: n }) }, } } })() Samtidighed i Java del 1 - Introduktion - The Codest
Codest
  • Om os
  • Serviceydelser
    • Udvikling af software
      • Frontend-udvikling
      • Backend-udvikling
    • Staff Augmentation
      • Frontend-udviklere
      • Backend-udviklere
      • Dataingeniører
      • Cloud-ingeniører
      • QA-ingeniører
      • Andet
    • Det rådgivende
      • Revision og rådgivning
  • Industrier
    • Fintech og bankvirksomhed
    • E-commerce
    • Adtech
    • Sundhedsteknologi
    • Produktion
    • Logistik
    • Biler
    • IOT
  • Værdi for
    • ADMINISTRERENDE DIREKTØR
    • CTO
    • Leder af levering
  • Vores team
  • Casestudier
  • Ved hvordan
    • Blog
    • Møder
    • Webinarer
    • Ressourcer
Karriere Tag kontakt til os
  • Om os
  • Serviceydelser
    • Udvikling af software
      • Frontend-udvikling
      • Backend-udvikling
    • Staff Augmentation
      • Frontend-udviklere
      • Backend-udviklere
      • Dataingeniører
      • Cloud-ingeniører
      • QA-ingeniører
      • Andet
    • Det rådgivende
      • Revision og rådgivning
  • Værdi for
    • ADMINISTRERENDE DIREKTØR
    • CTO
    • Leder af levering
  • Vores team
  • Casestudier
  • Ved hvordan
    • Blog
    • Møder
    • Webinarer
    • Ressourcer
Karriere Tag kontakt til os
Pil tilbage GÅ TILBAGE
2022-06-15
Udvikling af software

Samtidighed i Java del 1 - Introduktion

Codest

Rafal Sawicki

Java-udvikler

Læs første del af vores blogserie om samtidighed i Java. I den følgende artikel vil vi se nærmere på forskellene mellem tråd og proces, trådpuljer, eksekutorer og meget mere!

Generelt er den konventionelle programmeringstilgang sekventiel. Alt i et program sker et trin ad gangen.
Men faktisk er det parallelle den måde, hele verden kører på - det er evnen til at udføre mere end én opgave samtidig.

Tråd vs. proces

At diskutere avancerede emner som samtidighed i Java eller multithreading, er vi nødt til at aftale nogle fælles definitioner for at være sikre på, at vi er på samme side.

Lad os starte med det grundlæggende. I den ikke-sekventielle verden har vi to slags samtidighedsrepræsentanter: processer og
tråde. En proces er en instans af det program, der kører. Normalt er den isoleret fra andre processer.
Operativsystemet er ansvarligt for at tildele ressourcer til hver proces. Desuden fungerer det som en leder, der
planlægger og kontrollerer dem.

En tråd er en slags proces, men på et lavere niveau, og derfor kaldes den også en let tråd. Flere tråde kan køre i en
proces. Her fungerer programmet som en scheduler og en controller for tråde. På denne måde ser de enkelte programmer ud til at gøre
flere opgaver på samme tid.

Den grundlæggende forskel mellem tråde og processer er isolationsniveauet. Processen har sit eget sæt af
ressourcer, mens tråden deler data med andre tråde. Det kan virke som en fejlbehæftet tilgang, og det er det også. For
Lad os nu ikke fokusere på det, da det ligger uden for rammerne af denne artikel.

Processer, tråde - ok ... Men hvad er egentlig samtidighed? Samtidighed betyder, at du kan udføre flere opgaver på samme tid.
tid. Det betyder ikke, at de opgaver skal køre samtidig - det er det, der er parallelisme. Concurrenc i Javay gør det heller ikke
kræver, at du har flere CPU'er eller endda flere kerner. Det kan opnås i et miljø med én kerne ved at udnytte
skift af kontekst.

Et begreb, der er relateret til samtidighed, er multithreading. Det er en funktion i programmer, der gør det muligt for dem at udføre flere opgaver på én gang. Ikke alle programmer bruger denne tilgang, men dem, der gør, kan kaldes flertrådede.

Vi er næsten klar til at gå i gang, bare en definition mere. Asynkroni betyder, at et program udfører ikke-blokerende operationer.
Den påbegynder en opgave og fortsætter derefter med andre ting, mens den venter på responsen. Når den får svaret, kan den reagere på det.

Alt det der jazz

Som standard vil hver Java-applikation kører i én proces. I den proces er der en tråd, der er relateret til main() metode til
en applikation. Men som nævnt er det muligt at udnytte mekanismerne i flere tråde inden for en
program.

Kan køres

Tråd er en Java klasse, hvor magien sker. Dette er objektrepræsentationen af den førnævnte tråd. Til
oprette din egen tråd, kan du udvide Tråd klasse. Det er dog ikke en anbefalet tilgang. Tråde skal bruges som en mekanisme, der kører opgaven. Opgaver er dele af Kode som vi ønsker at køre i en samtidig tilstand. Vi kan definere dem ved hjælp af Kan køres interface.

Men nok teori, lad os bruge vores kode, hvor vores mund er.

Problem

Lad os antage, at vi har et par arrays af tal. For hver matrix vil vi gerne vide, hvad summen af tallene i en matrix er. Lad os
Lad som om der er mange af den slags arrays, og hver af dem er relativt store. Under sådanne forhold vil vi gøre brug af samtidighed og summere hvert array som en separat opgave.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10};
int[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7};

Runnable task1 = () -> {
    int sum = Arrays.stream(a1).sum();
    System.out.println("1. Summen er: " + sum);
};

Runnable task2 = () -> {
    int sum = Arrays.stream(a2).sum();
    System.out.println("2. Summen er: " + sum);
};

Runnable task3 = () -> {
    int sum = Arrays.stream(a3).sum();
    System.out.println("3. Summen er: " + sum);
};

new Thread(task1).start();
new Thread(task2).start();
new Thread(task3).start();

Som du kan se i koden ovenfor Kan køres er en funktionel grænseflade. Den indeholder en enkelt abstrakt metode kør()
uden argumenter. Den Kan køres interface bør implementeres af enhver klasse, hvis instanser er beregnet til at være
udført af en tråd.

Når du har defineret en opgave, kan du oprette en tråd til at køre den. Dette kan gøres via ny tråd() konstruktør, der
tager Kan køres som sit argument.

Det sidste skridt er at start() en nyoprettet tråd. I API'en er der også kør() metoder i Kan køres og i
Tråd. Men det er ikke en måde at udnytte samtidighed på i Java. Et direkte kald til hver af disse metoder resulterer i
udføre opgaven i den samme tråd som main() metoden kører.

Trådpuljer og eksekutorer

Når der er mange opgaver, er det ikke en god idé at oprette en separat tråd for hver enkelt. Oprettelse af en Tråd er en
tung operation, og det er langt bedre at genbruge eksisterende tråde end at oprette nye.

Når et program opretter mange kortvarige tråde, er det bedre at bruge en trådpulje. Trådpuljen indeholder et antal
klar til at køre, men i øjeblikket ikke aktive tråde. At give en Kan køres til puljen får en af trådene til at kalde
kør() metode af givet Kan køres. Når en opgave er afsluttet, eksisterer tråden stadig og er i en inaktiv tilstand.

Okay, du har forstået det - du foretrækker trådpuljer i stedet for manuel oprettelse. Men hvordan kan du gøre brug af trådpuljer? Den Eksekutorer
Klassen har en række statiske fabriksmetoder til konstruktion af trådpuljer. For eksempel newCachedThredPool() skaber
en pulje, hvor nye tråde oprettes efter behov, og inaktive tråde opbevares i 60 sekunder. I modsætning hertil,
newFixedThreadPool() indeholder et fast sæt af tråde, hvor inaktive tråde opbevares på ubestemt tid.

Lad os se, hvordan det kan fungere i vores eksempel. Nu behøver vi ikke at oprette tråde manuelt. I stedet skal vi oprette
UdførerService som giver en pulje af tråde. Derefter kan vi tildele opgaver til den. Det sidste trin er at lukke tråden
pool for at undgå hukommelseslækager. Resten af den tidligere kode forbliver den samme.

ExecutorService executor = Executors.newCachedThreadPool();

executor.submit(opgave1);
executor.submit(opgave2);
executor.submit(opgave3);

executor.shutdown();

Kan kaldes

Kan køres virker som en smart måde at skabe samtidige opgaver på, men den har en stor mangel. Den kan ikke returnere nogen
værdi. Desuden kan vi ikke afgøre, om en opgave er færdig eller ej. Vi ved heller ikke, om den er afsluttet.
normalt eller usædvanligt. Løsningen på disse problemer er Kan kaldes.

Kan kaldes svarer til Kan køres På en måde omslutter den også asynkrone opgaver. Den største forskel er, at den er i stand til at
returnere en værdi. Returværdien kan være af en hvilken som helst (ikke-primitiv) type, da Kan kaldes interface er en parameteriseret type.
Kan kaldes er en funktionel grænseflade, der har opkald() metode, som kan kaste en Undtagelse.

Lad os nu se, hvordan vi kan udnytte Kan kaldes i vores array-problem.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10};
int[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7};

Callable task1 = () -> Arrays.stream(a1).sum();
Callable task2 = () -> Arrays.stream(a2).sum();
Callable task3 = () -> Arrays.stream(a3).sum();

ExecutorService executor = Executors.newCachedThreadPool();
Future future1 = executor.submit(task1);
Future future2 = executor.submit(task2);
Future future3 = executor.submit(task3);

System.out.println("1. Summen er: " + future1.get());
System.out.println("2. Summen er: " + future2.get());
System.out.println("3. Summen er: " + future3.get());

executor.shutdown();

Okay, vi kan se, hvordan Kan kaldes oprettes og sendes derefter til UdførerService. Men hvad pokker er Fremtiden?
Fremtiden fungerer som en bro mellem trådene. Summen af hvert array produceres i en separat tråd, og vi har brug for en måde at
få disse resultater tilbage til main().

For at hente resultatet fra Fremtiden Vi er nødt til at ringe get() metode. Her kan der ske en af to ting. For det første kan
resultatet af den beregning, der udføres af Kan kaldes er tilgængelig. Så får vi det med det samme. For det andet er resultatet ikke
klar endnu. I det tilfælde get() metoden vil blokere, indtil resultatet er tilgængeligt.

ComputableFuture

Problemet med Fremtiden er, at det fungerer i 'push-paradigmet'. Når man bruger Fremtiden Du skal være som en chef, der
spørger konstant: "Er din opgave færdig? Er den klar?", indtil den giver et resultat. At handle under konstant pres er
dyrt. En langt bedre tilgang ville være at bestille Fremtiden hvad den skal gøre, når den er klar med sin opgave. Desværre,
Fremtiden kan ikke gøre det, men ComputableFuture kan.

ComputableFuture arbejder i 'pull-paradigmet'. Vi kan fortælle den, hvad den skal gøre med resultatet, når den er færdig med sine opgaver. Den
er et eksempel på en asynkron tilgang.

ComputableFuture fungerer perfekt med Kan køres men ikke med Kan kaldes. I stedet er det muligt at levere en opgave til
ComputableFuture i form af Leverandør.

Lad os se, hvordan ovenstående hænger sammen med vores problem.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10};
int[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7};

CompletableFuture.supplyAsync(() -> Arrays.stream(a1).sum())
                .thenAccept(System.out::println);

CompletableFuture.supplyAsync(() -> Arrays.stream(a2).sum())
                .thenAccept(System.out::println);

CompletableFuture.supplyAsync(() -> Arrays.stream(a3).sum())
                .thenAccept(System.out::println);

Det første, der slår dig, er, hvor meget kortere denne løsning er. Desuden ser det også pænt og ryddeligt ud.

Opgave til FuldstændigFremtid kan leveres af supplyAsync() metode, der tager Leverandør eller af runAsync() at
tager Kan køres. Et tilbagekald - et stykke kode, der skal køres, når opgaven er fuldført - defineres af thenAccept()
metode.

Konklusioner

Java giver mange forskellige tilgange til samtidighed. I denne artikel har vi kun lige berørt emnet.

Ikke desto mindre dækkede vi det grundlæggende i Tråd, Kan køres, Kan kaldesog CallableFuture hvilket er en god pointe
for yderligere undersøgelse af emnet.

Relaterede artikler

Udvikling af software

9 fejl, du skal undgå, når du programmerer i Java

Hvilke fejl bør man undgå, når man programmerer i Java? I det følgende afsnit besvarer vi dette spørgsmål.

Codest
Rafal Sawicki Java-udvikler
Løsninger til virksomheder og scaleups

Den rigtige måde at finde de bedste Java-udviklere på

At finde den perfekte Java-udvikler kan være en skræmmende opgave. Da markedets efterspørgsel efter sådanne fagfolk vokser i et forbløffende tempo, kan de tilgængelige kilder til talentsøgning nogle gange virke...

Codest
Grzegorz Rozmus Leder af Java-enhed
Løsninger til virksomheder og scaleups

10 Dubai-virksomheder, der er værd at holde øje med i 2020

Dubai er hjertet i De Forenede Arabiske Emirater med sit stadig mere velstående marked af globale virksomheder og lovende startups. Mange kan prale af deres internationale succes og bemærkelsesværdige produkter....

Tunfisk Pinar
Løsninger til virksomheder og scaleups

Hvordan kan Java støtte din virksomhed?

Før vi går i gang, vil jeg gerne minde dig om en vigtig ting. Java er ikke kun et programmeringssprog.

Bartlomiej Kuczynski
Løsninger til virksomheder og scaleups

En dag i en programmørs liv hos The Codest

Du tror måske, at programmørers arbejdsplaner ikke adskiller sig fra hinanden. Men det er faktisk ikke sandt! Hver enkelt startup, softwarehus og endda virksomhed har sin egen...

Codest
Pawel Rybczynski Software Engineer

Tilmeld dig vores vidensbase, og hold dig opdateret om ekspertisen fra it-sektoren.

    Om os

    The Codest - International softwareudviklingsvirksomhed med tech-hubs i Polen.

    Storbritannien - Hovedkvarter

    • Kontor 303B, 182-184 High Street North E6 2JA
      London, England

    Polen - Lokale teknologiske knudepunkter

    • Fabryczna Office Park, Aleja
      Pokoju 18, 31-564 Kraków
    • Hjerneambassaden, Konstruktorska
      11, 02-673 Warszawa, Polen

      Codest

    • Hjem
    • Om os
    • Serviceydelser
    • Casestudier
    • Ved hvordan
    • Karriere
    • Ordbog

      Serviceydelser

    • Det rådgivende
    • Udvikling af software
    • Backend-udvikling
    • Frontend-udvikling
    • Staff Augmentation
    • Backend-udviklere
    • Cloud-ingeniører
    • Dataingeniører
    • Andet
    • QA-ingeniører

      Ressourcer

    • Fakta og myter om at samarbejde med en ekstern softwareudviklingspartner
    • Fra USA til Europa: Hvorfor beslutter amerikanske startups sig for at flytte til Europa?
    • Sammenligning af Tech Offshore-udviklingsknudepunkter: Tech Offshore Europa (Polen), ASEAN (Filippinerne), Eurasien (Tyrkiet)
    • Hvad er de største udfordringer for CTO'er og CIO'er?
    • Codest
    • Codest
    • Codest
    • Privacy policy
    • Vilkår for brug af hjemmesiden

    Copyright © 2025 af The Codest. Alle rettigheder forbeholdes.

    da_DKDanish
    en_USEnglish de_DEGerman sv_SESwedish nb_NONorwegian fiFinnish fr_FRFrench pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek da_DKDanish