Forkjoinpool
ForkJoinPool-klassen i Java til arbejde med Fork/Join-frameworket er netop realiseringen af dette. Den tilbyder mekanismer til håndtering af opgaver, der kan opdeles i mindre delopgaver og udføres parallelt.
Main.java
1ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinPool er baseret på konceptet om to grundlæggende handlinger: fork og join. Fork er en handling, hvor en stor opgave opdeles i flere mindre delopgaver, der kan udføres parallelt. Join er processen, hvor resultaterne af disse delopgaver kombineres for at danne resultatet af den oprindelige opgave.
Case Study
Forestil dig, at du skal analysere et enormt datasæt, som kan opdeles i flere mindre sæt. Hvis hvert datasæt behandles separat og resultaterne derefter sammenflettes, kan behandlingen fremskyndes betydeligt, især på multiprocessorsystemer.
Sådan bruges ForkJoinPool
Der findes 2 klasser til implementering af opgaver i dem, nemlig RecursiveTask og RecursiveAction. Begge kræver, at den abstrakte metode compute() implementeres. I RecursiveTask returnerer metoden compute() en værdi, mens RecursiveAction-metoden i compute() returnerer void.
Main.java
12345678class ExampleTask extends RecursiveTask<String> { @Override protected String compute() { // code return null; } }
Når vi arver fra en RecursiveTask, skal vi sikre os at angive, hvilken datatype vores compute()-metode vil returnere ved at bruge denne syntaks RecursiveTask<String>.
Main.java
1234567class ExampleAction extends RecursiveAction { @Override protected void compute() { // code } }
Her er det omvendt, vi behøver ikke at angive typen eksplicit i RecursiveAction, fordi vores metode ikke returnerer noget og blot udfører opgaven.
Start af en opgave
Bemærk, at vi kan starte en opgave til udførelse uden at bruge ForkJoinPool, blot ved at anvende metoderne fork() og join().
Det er vigtigt at bemærke, at metoden fork() sender opgaven til en tråd. Metoden join() bruges til at hente resultatet.
Main.java
12345public static void main(String[] args) { ExampleTask simpleClass = new ExampleTask(); simpleClass.fork(); System.out.println(simpleClass.join()); }
ForkJoinPool Hovedmetoder
invoke(): Starter en opgave i poolen og venter på, at den fuldføres. Returnerer resultatet af opgavens fuldførelse;submit(): Indsender en opgave til poolen, men blokerer ikke den aktuelle tråd, mens den venter på, at opgaven fuldføres. Kan bruges til at indsende opgaver og hente deresFuture-objekter;execute(): Kører en opgave i poolen, men returnerer ikke et resultat og blokerer ikke den aktuelle tråd.
Hvordan kan vi starte en opgave ved hjælp af ForkJoinPool, meget enkelt!
Main.java
12345public static void main(String[] args) { ExampleAction simpleClass = new ExampleAction(); ForkJoinPool forkJoinPool = new ForkJoinPool(); System.out.println(forkJoinPool.invoke(simpleClass)); }
Men hvad er forskellen på at køre fork(), join() og via ForkJoinPool klassen?
Det er meget enkelt! Når man bruger den første metode med fork(), join() metoderne, starter vi opgaven i den samme tråd, hvor disse metoder blev kaldt, hvilket blokerer denne tråd, mens vi med ForkJoinPool klassen får tildelt en tråd fra puljen, og den arbejder i denne tråd uden at blokere hovedtråden.
Lad os se nærmere på det, antag at vi har en sådan implementering:
Main.java
12345678class ExampleRecursiveTask extends RecursiveTask<String> { @Override protected String compute() { System.out.println("Thread: " + Thread.currentThread().getName()); return "Wow, it works!!!"; } }
Og vi ønsker at køre denne kode ved hjælp af fork() og join(). Lad os se, hvad der vil blive udskrevet til konsollen, og hvilken tråd der vil udføre denne opgave.
Main.java
1234567public class Main { public static void main(String[] args) { ExampleRecursiveTask simpleClass = new ExampleRecursiveTask(); simpleClass.fork(); System.out.println(simpleClass.join()); } }
Og vi får denne output i konsollen:
Thread: main
Wow, it works!!!
Lad os nu se, hvad der sker, hvis vi kører med ForkJoinPool:
Main.java
1234567public class Main { public static void main(String[] args) { ExampleRecursiveTask simpleClass = new ExampleRecursiveTask(); ForkJoinPool forkJoinPool = new ForkJoinPool(); System.out.println(forkJoinPool.invoke(simpleClass)); } }
Og vi får denne konklusion:
Thread: ForkJoinPool-1-worker-1
Wow, it works!!!
Som det kan ses, er forskellen at ved brug af første metode udføres opgaven i den samme tråd, der kaldte denne opgave (Main thread). Men hvis vi bruger anden metode, tages tråden fra ForkJoinPool tråd-poolen, og hovedtråden, der kaldte denne logik, blokeres ikke og fortsætter!
Sådan implementeres Fork/Join i kode
Den nemmeste måde at forklare dette på ville være i en video, frem for at give dig 50-80 linjer kode og forklare det punkt for punkt.
ForkJoinPool er effektiv til opgaver, der let kan opdeles i mindre delopgaver. Hvis opgaverne dog er for små, kan brugen af ForkJoinPool ikke give en væsentlig ydelsesforbedring.
Tak for dine kommentarer!
Spørg AI
Spørg AI
Spørg om hvad som helst eller prøv et af de foreslåede spørgsmål for at starte vores chat
Can you explain the difference between RecursiveTask and RecursiveAction again?
How do I decide what threshold to use when splitting tasks?
Can you give a simple code example of using ForkJoinPool?
Awesome!
Completion rate improved to 3.33
Forkjoinpool
Stryg for at vise menuen
ForkJoinPool-klassen i Java til arbejde med Fork/Join-frameworket er netop realiseringen af dette. Den tilbyder mekanismer til håndtering af opgaver, der kan opdeles i mindre delopgaver og udføres parallelt.
Main.java
1ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinPool er baseret på konceptet om to grundlæggende handlinger: fork og join. Fork er en handling, hvor en stor opgave opdeles i flere mindre delopgaver, der kan udføres parallelt. Join er processen, hvor resultaterne af disse delopgaver kombineres for at danne resultatet af den oprindelige opgave.
Case Study
Forestil dig, at du skal analysere et enormt datasæt, som kan opdeles i flere mindre sæt. Hvis hvert datasæt behandles separat og resultaterne derefter sammenflettes, kan behandlingen fremskyndes betydeligt, især på multiprocessorsystemer.
Sådan bruges ForkJoinPool
Der findes 2 klasser til implementering af opgaver i dem, nemlig RecursiveTask og RecursiveAction. Begge kræver, at den abstrakte metode compute() implementeres. I RecursiveTask returnerer metoden compute() en værdi, mens RecursiveAction-metoden i compute() returnerer void.
Main.java
12345678class ExampleTask extends RecursiveTask<String> { @Override protected String compute() { // code return null; } }
Når vi arver fra en RecursiveTask, skal vi sikre os at angive, hvilken datatype vores compute()-metode vil returnere ved at bruge denne syntaks RecursiveTask<String>.
Main.java
1234567class ExampleAction extends RecursiveAction { @Override protected void compute() { // code } }
Her er det omvendt, vi behøver ikke at angive typen eksplicit i RecursiveAction, fordi vores metode ikke returnerer noget og blot udfører opgaven.
Start af en opgave
Bemærk, at vi kan starte en opgave til udførelse uden at bruge ForkJoinPool, blot ved at anvende metoderne fork() og join().
Det er vigtigt at bemærke, at metoden fork() sender opgaven til en tråd. Metoden join() bruges til at hente resultatet.
Main.java
12345public static void main(String[] args) { ExampleTask simpleClass = new ExampleTask(); simpleClass.fork(); System.out.println(simpleClass.join()); }
ForkJoinPool Hovedmetoder
invoke(): Starter en opgave i poolen og venter på, at den fuldføres. Returnerer resultatet af opgavens fuldførelse;submit(): Indsender en opgave til poolen, men blokerer ikke den aktuelle tråd, mens den venter på, at opgaven fuldføres. Kan bruges til at indsende opgaver og hente deresFuture-objekter;execute(): Kører en opgave i poolen, men returnerer ikke et resultat og blokerer ikke den aktuelle tråd.
Hvordan kan vi starte en opgave ved hjælp af ForkJoinPool, meget enkelt!
Main.java
12345public static void main(String[] args) { ExampleAction simpleClass = new ExampleAction(); ForkJoinPool forkJoinPool = new ForkJoinPool(); System.out.println(forkJoinPool.invoke(simpleClass)); }
Men hvad er forskellen på at køre fork(), join() og via ForkJoinPool klassen?
Det er meget enkelt! Når man bruger den første metode med fork(), join() metoderne, starter vi opgaven i den samme tråd, hvor disse metoder blev kaldt, hvilket blokerer denne tråd, mens vi med ForkJoinPool klassen får tildelt en tråd fra puljen, og den arbejder i denne tråd uden at blokere hovedtråden.
Lad os se nærmere på det, antag at vi har en sådan implementering:
Main.java
12345678class ExampleRecursiveTask extends RecursiveTask<String> { @Override protected String compute() { System.out.println("Thread: " + Thread.currentThread().getName()); return "Wow, it works!!!"; } }
Og vi ønsker at køre denne kode ved hjælp af fork() og join(). Lad os se, hvad der vil blive udskrevet til konsollen, og hvilken tråd der vil udføre denne opgave.
Main.java
1234567public class Main { public static void main(String[] args) { ExampleRecursiveTask simpleClass = new ExampleRecursiveTask(); simpleClass.fork(); System.out.println(simpleClass.join()); } }
Og vi får denne output i konsollen:
Thread: main
Wow, it works!!!
Lad os nu se, hvad der sker, hvis vi kører med ForkJoinPool:
Main.java
1234567public class Main { public static void main(String[] args) { ExampleRecursiveTask simpleClass = new ExampleRecursiveTask(); ForkJoinPool forkJoinPool = new ForkJoinPool(); System.out.println(forkJoinPool.invoke(simpleClass)); } }
Og vi får denne konklusion:
Thread: ForkJoinPool-1-worker-1
Wow, it works!!!
Som det kan ses, er forskellen at ved brug af første metode udføres opgaven i den samme tråd, der kaldte denne opgave (Main thread). Men hvis vi bruger anden metode, tages tråden fra ForkJoinPool tråd-poolen, og hovedtråden, der kaldte denne logik, blokeres ikke og fortsætter!
Sådan implementeres Fork/Join i kode
Den nemmeste måde at forklare dette på ville være i en video, frem for at give dig 50-80 linjer kode og forklare det punkt for punkt.
ForkJoinPool er effektiv til opgaver, der let kan opdeles i mindre delopgaver. Hvis opgaverne dog er for små, kan brugen af ForkJoinPool ikke give en væsentlig ydelsesforbedring.
Tak for dine kommentarer!