window.pipedriveLeadboosterConfig = { base: 'leadbooster-chat.pipedrive.com', companyId: 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', versjon: 2, } ;(function () { var w = vindu if (w.LeadBooster) { console.warn('LeadBooster finnes 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 }) }, } } })() Samtidighet i Java del 1 - Introduksjon - The Codest
The Codest
  • Om oss
  • Tjenester
    • Programvareutvikling
      • Frontend-utvikling
      • Backend-utvikling
    • Staff Augmentation
      • Frontend-utviklere
      • Backend-utviklere
      • Dataingeniører
      • Ingeniører i skyen
      • QA-ingeniører
      • Annet
    • Det rådgivende
      • Revisjon og rådgivning
  • Industrier
    • Fintech og bankvirksomhet
    • E-commerce
    • Adtech
    • Helseteknologi
    • Produksjon
    • Logistikk
    • Bilindustrien
    • IOT
  • Verdi for
    • ADMINISTRERENDE DIREKTØR
    • CTO
    • Leveransesjef
  • Vårt team
  • Casestudier
  • Vet hvordan
    • Blogg
    • Møter
    • Webinarer
    • Ressurser
Karriere Ta kontakt med oss
  • Om oss
  • Tjenester
    • Programvareutvikling
      • Frontend-utvikling
      • Backend-utvikling
    • Staff Augmentation
      • Frontend-utviklere
      • Backend-utviklere
      • Dataingeniører
      • Ingeniører i skyen
      • QA-ingeniører
      • Annet
    • Det rådgivende
      • Revisjon og rådgivning
  • Verdi for
    • ADMINISTRERENDE DIREKTØR
    • CTO
    • Leveransesjef
  • Vårt team
  • Casestudier
  • Vet hvordan
    • Blogg
    • Møter
    • Webinarer
    • Ressurser
Karriere Ta kontakt med oss
Pil tilbake GÅ TILBAKE
2022-06-15
Programvareutvikling

Samtidighet i Java Del 1 - Introduksjon

The Codest

Rafal Sawicki

Java-utvikler

Les første del av bloggserien vår om samtidighet i Java. I den følgende artikkelen skal vi se nærmere på forskjellene mellom tråd og prosess, trådbassenger, eksekutorer og mye mer!

Generelt er den konvensjonelle programmeringstilnærmingen sekvensiell. Alt i et program skjer ett steg om gangen.
Men faktisk er det parallellkjøringen som styrer hele verden - det er evnen til å utføre mer enn én oppgave samtidig.

Tråd vs. prosess

For å diskutere avanserte emner som samtidighet i Java eller flertråding, må vi bli enige om noen felles definisjoner for å være sikre på at vi er på samme side.

La oss begynne med det grunnleggende. I den ikke-sekvensielle verdenen har vi to typer samtidighetsrepresentanter: prosesser og
tråder. En prosess er en instans av programmet som kjører. Normalt er den isolert fra andre prosesser.
Operativsystemet er ansvarlig for å tildele ressurser til hver prosess. I tillegg fungerer det som en dirigent som
planlegger og kontrollerer dem.

En tråd er en slags prosess, men på et lavere nivå, derfor kalles den også lett tråd. Flere tråder kan kjøre i én
prosess. Her fungerer programmet som en planlegger og en kontrollør for tråder. På denne måten ser det ut til at de enkelte programmene gjør
flere oppgaver samtidig.

Den grunnleggende forskjellen mellom tråder og prosesser er isolasjonsnivået. Prosessen har sitt eget sett med
ressurser, mens tråden deler data med andre tråder. Det kan virke som en feilutsatt tilnærming, og det er det også. For
Nå skal vi ikke fokusere på det, for det ligger utenfor denne artikkelen.

Prosesser, tråder - ok ... Men hva er egentlig samtidighet? Samtidighet betyr at du kan utføre flere oppgaver samtidig.
tid. Det betyr ikke at disse oppgavene må kjøres samtidig - det er det som er parallellisme. Concurrenc i Javay gjør heller ikke
krever at du har flere CPU-er eller til og med flere kjerner. Det kan oppnås i et enkeltkjernemiljø ved å utnytte
bytte av kontekst.

Et begrep som er relatert til samtidighet, er multithreading. Dette er en egenskap ved programmer som gjør at de kan utføre flere oppgaver samtidig. Ikke alle programmer bruker denne tilnærmingen, men de som gjør det, kan kalles flertrådede.

Vi er nesten klare, bare én definisjon til. Asynkronitet betyr at et program utfører ikke-blokkerende operasjoner.
Den setter i gang en oppgave og fortsetter med andre ting mens den venter på responsen. Når den får responsen, kan den reagere på den.

Alt det der jazz

Som standard vil hver Java-applikasjon kjører i én prosess. I denne prosessen er det én tråd knyttet til main() metode for
en applikasjon. Som nevnt er det imidlertid mulig å utnytte mekanismene for flere tråder i en og samme
program.

Kjørbar

Tråd er en Java klassen der magien skjer. Dette er objektrepresentasjonen av den tidligere nevnte tråden. Til
lage din egen tråd, kan du utvide Tråd klasse. Det er imidlertid ikke en anbefalt tilnærming. Tråder skal brukes som en mekanisme som kjører oppgaven. Oppgaver er deler av kode som vi ønsker å kjøre i samtidig modus. Vi kan definere dem ved hjelp av Kjørbar grensesnitt.

Men nok teori, la oss sette koden der vi snakker.

Problem

Anta at vi har et par matriser med tall. For hver matrise ønsker vi å vite summen av tallene i en matrise. La oss
Vi later som om det finnes mange slike matriser, og hver av dem er relativt store. Under slike forhold ønsker vi å utnytte samtidighet og summere hver matrise som en separat oppgave.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
int[] a3 = {3, 4, 3, 4, 3, 4, 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 av koden ovenfor Kjørbar er et funksjonelt grensesnitt. Det inneholder en enkelt abstrakt metode run()
uten argumenter. Den Kjørbar grensesnittet bør implementeres av alle klasser hvis instanser er ment å være
utført av en tråd.

Når du har definert en oppgave, kan du opprette en tråd for å kjøre den. Dette kan gjøres via ny tråd() konstruktør som
tar Kjørbar som sitt argument.

Det siste trinnet er å start() en nyopprettet tråd. I API-et finnes det også run() metoder i Kjørbar og i
Tråd. Det er imidlertid ikke en måte å utnytte samtidighet på i Java. Et direkte anrop til hver av disse metodene resulterer i
utføre oppgaven i samme tråd som main() metoden kjører.

Trådpooler og eksekutorer

Når det er mange oppgaver, er det ikke lurt å opprette en egen tråd for hver av dem. Å opprette en Tråd er en
tungvint operasjon, og det er langt bedre å gjenbruke eksisterende tråder enn å opprette nye.

Når et program oppretter mange kortvarige tråder, er det bedre å bruke et trådbasseng. Trådbassenget inneholder et antall
som er klare til å kjøre, men som for øyeblikket ikke er aktive. Å gi en Kjørbar til poolen fører til at en av trådene kaller
run() metode for gitt Kjørbar. Etter at en oppgave er fullført, eksisterer tråden fortsatt og er i en inaktiv tilstand.

Ok, du skjønner det - du foretrekker trådpooler i stedet for manuell oppretting. Men hvordan kan du bruke trådbassenger? Det Eksekutorer
klassen har en rekke statiske fabrikkmetoder for konstruksjon av trådpooler. For eksempel newCachedThredPool() skaper
en pool der nye tråder opprettes etter behov, og inaktive tråder beholdes i 60 sekunder. I motsetning til dette,
newFixedThreadPool() inneholder et fast sett med tråder, der inaktive tråder beholdes på ubestemt tid.

La oss se hvordan det kan fungere i vårt eksempel. Nå trenger vi ikke å opprette tråder manuelt. I stedet må vi opprette
ExecutorService som gir en pool av tråder. Deretter kan vi tildele oppgaver til den. Det siste trinnet er å lukke tråden
for å unngå minnelekkasjer. Resten av den forrige koden forblir den samme.

ExecutorService executor = Executors.newCachedThreadPool();

executor.submit(oppgave1);
executor.submit(oppgave2);
executor.submit(oppgave3);

executor.shutdown();

Kan kalles

Kjørbar virker som en smart måte å opprette samtidige oppgaver på, men den har en stor svakhet. Den kan ikke returnere noen
verdi. Dessuten kan vi ikke avgjøre om en oppgave er ferdig eller ikke. Vi vet heller ikke om den er fullført
normalt eller unntaksvis. Løsningen på disse problemene er Kan kalles.

Kan kalles ligner på Kjørbar på en måte også asynkrone oppgaver. Hovedforskjellen er at den er i stand til å
returnerer en verdi. Returverdien kan være av en hvilken som helst (ikke-primitiv) type, ettersom Kan kalles grensesnittet er en parametrisert type.
Kan kalles er et funksjonelt grensesnitt som har call() metode som kan kaste en Unntak.

La oss nå se hvordan vi kan utnytte Kan kalles i matriseproblemet vårt.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
int[] a3 = {3, 4, 3, 4, 3, 4, 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();

Ok, vi kan se hvordan Kan kalles opprettes og sendes deretter til ExecutorService. Men hva pokker er Fremtiden?
Fremtiden fungerer som en bro mellom trådene. Summen av hver matrise produseres i en separat tråd, og vi trenger en måte å
få disse resultatene tilbake til main().

For å hente resultatet fra Fremtiden må vi ringe get() metode. Her kan en av to ting skje. For det første kan
resultatet av beregningen utført av Kan kalles er tilgjengelig. Da får vi det umiddelbart. For det andre er resultatet ikke
klar ennå. I så fall get() metoden vil blokkere til resultatet er tilgjengelig.

ComputableFuture

Problemet med Fremtiden er at den fungerer i "push-paradigmet". Når du bruker Fremtiden må du være som en sjef som
spør hele tiden: "Er oppgaven din ferdig? Er den klar?" helt til den gir et resultat. Å handle under konstant press er
dyrt. En mye bedre tilnærming ville være å bestille Fremtiden hva den skal gjøre når den er ferdig med oppgaven sin. Dessverre,
Fremtiden kan ikke gjøre det, men ComputableFuture kan.

ComputableFuture fungerer i "pull-paradigmet". Vi kan fortelle den hva den skal gjøre med resultatet når den er ferdig med oppgavene sine. Det
er et eksempel på en asynkron tilnærming.

ComputableFuture fungerer perfekt med Kjørbar men ikke med Kan kalles. I stedet er det mulig å levere en oppgave til
ComputableFuture i form av Leverandør.

La oss se hvordan dette henger sammen med problemet vårt.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10, 10};
int[] a3 = {3, 4, 3, 4, 3, 4, 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 som slår deg er hvor mye kortere denne løsningen er. I tillegg ser det også pent og ryddig ut.

Oppgave til CompletableFuture kan leveres av supplyAsync() metode som tar Leverandør eller av runAsync() at
tar Kjørbar. En tilbakekalling - et stykke kode som skal kjøres når oppgaven er fullført - defineres av thenAccept()
metode.

Konklusjoner

Java gir mange forskjellige tilnærminger til samtidighet. I denne artikkelen har vi så vidt berørt temaet.

Likevel har vi dekket det grunnleggende om Tråd, Kjørbar, Kan kalles, og CallableFuture noe som er et godt poeng
for videre utforskning av temaet.

Relaterte artikler

Programvareutvikling

9 feil du bør unngå når du programmerer i Java

Hvilke feil bør man unngå når man programmerer i Java? I det følgende besvarer vi dette spørsmålet.

The Codest
Rafal Sawicki Java-utvikler
Løsninger for bedrifter og oppskalering

Den riktige måten å finne de beste Java-utviklerne på

Å finne den perfekte Java-utvikleren kan være en krevende oppgave. Ettersom etterspørselen etter slike fagfolk vokser i et forbløffende tempo, kan tilgjengelige kilder for talentsøk noen ganger virke...

The Codest
Grzegorz Rozmus Leder for Java-enheten
Løsninger for bedrifter og oppskalering

10 Dubai-selskaper det er verdt å følge med på i 2020

Dubai er hjertet i De forente arabiske emirater, med et stadig mer fremgangsrikt marked av globale selskaper og lovende oppstartsbedrifter. Mange kan skryte av internasjonal suksess og bemerkelsesverdige produkter....

Tuna Pinar
Løsninger for bedrifter og oppskalering

Hvordan kan Java støtte virksomheten din?

Før vi begynner, vil jeg gjerne minne deg på en viktig ting. Java er ikke bare et programmeringsspråk.

Bartlomiej Kuczynski
Løsninger for bedrifter og oppskalering

En dag i livet til en programmerer hos The Codest

Du mistenker kanskje at arbeidsplanene til programmerere ikke skiller seg fra hverandre. Men dette er faktisk ikke sant! Hver oppstartsbedrift, programvarebedrift og til og med selskap har sine egne...

The Codest
Pawel Rybczynski Software Engineer

Abonner på vår kunnskapsbase og hold deg oppdatert på ekspertisen fra IT-sektoren.

    Om oss

    The Codest - Internasjonalt programvareutviklingsselskap med teknologisentre i Polen.

    Storbritannia - Hovedkvarter

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

    Polen - Lokale teknologisentre

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

      The Codest

    • Hjem
    • Om oss
    • Tjenester
    • Casestudier
    • Vet hvordan
    • Karriere
    • Ordbok

      Tjenester

    • Det rådgivende
    • Programvareutvikling
    • Backend-utvikling
    • Frontend-utvikling
    • Staff Augmentation
    • Backend-utviklere
    • Ingeniører i skyen
    • Dataingeniører
    • Annet
    • QA-ingeniører

      Ressurser

    • Fakta og myter om samarbeid med en ekstern programvareutviklingspartner
    • Fra USA til Europa: Hvorfor velger amerikanske oppstartsbedrifter å flytte til Europa?
    • Sammenligning av Tech Offshore Development Hubs: Tech Offshore Europa (Polen), ASEAN (Filippinene), Eurasia (Tyrkia)
    • Hva er de største utfordringene for CTO-er og CIO-er?
    • The Codest
    • The Codest
    • The Codest
    • Retningslinjer for personver
    • Vilkår for bruk av nettstedet

    Opphavsrett © 2025 av The Codest. Alle rettigheter forbeholdt.

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