Spring Batch - Taken versus brokken

1. Inleiding

Spring Batch biedt twee verschillende manieren om een ​​taak uit te voeren: met behulp van tasklets en brokken.

In dit artikel leren we hoe u beide methoden configureert en implementeert aan de hand van een eenvoudig voorbeeld uit de praktijk.

2. Afhankelijkheden

Laten we beginnen met het toevoegen van de vereiste afhankelijkheden:

 org.springframework.batch spring-batch-core 4.2.0.RELEASE org.springframework.batch spring-batch-test 4.2.0.RELEASE-test 

Raadpleeg Maven Central voor de nieuwste versie van spring-batch-core en spring-batch-test.

3. Onze use case

Laten we eens kijken naar een CSV-bestand met de volgende inhoud:

Mae Hodges, 22/10/1972 Gary Potter, 22/02/1953 Betty Wise, 17/2/1968 Wayne Rose, 06/04/1977 Adam Caldwell, 27/09/1995 Lucille Phillips, 14/05/1992

De eerste positie van elke regel vertegenwoordigt de naam van een persoon en de tweede positie vertegenwoordigt zijn / haar geboortedatum.

Onze use case is to genereer een ander CSV-bestand dat de naam en leeftijd van elke persoon bevat:

Mae Hodges, 45 Gary Potter, 64 Betty Wise, 49 Wayne Rose, 40 Adam Caldwell, 22 Lucille Phillips, 25

Nu ons domein duidelijk is, gaan we door en bouwen we een oplossing met beide benaderingen. We beginnen met tasklets.

4. Taakbenadering

4.1. Inleiding en ontwerp

Taken zijn bedoeld om een ​​enkele taak binnen een stap uit te voeren. Onze taak zal bestaan ​​uit verschillende stappen die na elkaar worden uitgevoerd. Elke stap zou slechts één gedefinieerde taak moeten uitvoeren.

Ons werk bestaat uit drie stappen:

  1. Lees regels uit het ingevoerde CSV-bestand.
  2. Bereken de leeftijd voor elke persoon in het ingevoerde CSV-bestand.
  3. Schrijf de naam en leeftijd van elke persoon in een nieuw CSV-uitvoerbestand.

Nu het grote geheel klaar is, gaan we één klas per stap maken.

LinesReader zal verantwoordelijk zijn voor het lezen van gegevens uit het invoerbestand:

openbare klasse LinesReader implementeert Tasklet {// ...}

LinesProcessor berekent de leeftijd voor elke persoon in het bestand:

openbare klasse LinesProcessor implementeert Tasklet {// ...}

Tenslotte, LinesWriter zal de verantwoordelijkheid hebben om namen en leeftijden naar een uitvoerbestand te schrijven:

openbare klasse LinesWriter implementeert Tasklet {// ...}

Op dit punt, al onze stappen implementeren Tasklet koppel. Dat zal ons dwingen zijn uitvoeren methode:

@Override public RepeatStatus uitvoeren (StepContribution stepContribution, ChunkContext chunkContext) genereert uitzondering {// ...}

Bij deze methode voegen we de logica voor elke stap toe. Laten we, voordat we met die code beginnen, onze taak configureren.

4.2. Configuratie

We moeten voeg wat configuratie toe aan de toepassingscontext van Spring. Na het toevoegen van een standaard bean-declaratie voor de klassen die in de vorige sectie zijn gemaakt, zijn we klaar om onze jobdefinitie te maken:

@Configuration @EnableBatchProcessing openbare klasse TaskletsConfig {@Autowired privé JobBuilderFactory-banen; @Autowired private StepBuilderFactory stappen; @Bean protected Step readLines () {retourstappen .get ("readLines") .tasklet (linesReader ()) .build (); } @Bean beschermde Step processLines () {retourstappen .get ("processLines") .tasklet (linesProcessor ()) .build (); } @Bean beschermde Step writeLines () {retourneer stappen .get ("writeLines") .tasklet (linesWriter ()) .build (); } @Bean openbare Job job () {retourneer jobs .get ("taskletsJob") .start (readLines ()) .next (processLines ()) .next (writeLines ()) .build (); } // ...}

Dit betekent dat onze "TaskletsJob" bestaat uit drie stappen. De eerste (readLines) zal de tasklet uitvoeren die in de bean is gedefinieerd linesReader en ga naar de volgende stap: processLines. ProcessLines voert de tasklet uit die in de bean is gedefinieerd linesProcessor en ga naar de laatste stap: writeLines.

Onze jobflow is gedefinieerd en we zijn klaar om wat logica toe te voegen!

4.3. Model en gebruik

Omdat we regels in een CSV-bestand gaan manipuleren, gaan we een klasse maken Lijn:

public class Line implementeert Serializable {private String name; privé LocalDate dob; privé Lange leeftijd; // standard constructor, getters, setters en toString implementatie}

Houd er rekening mee dat Lijn werktuigen Serialiseerbaar. Dat is omdat Lijn zal optreden als een DTO om gegevens tussen de stappen uit te wisselen. Volgens Spring Batch, objecten die tussen stappen worden overgedragen, moeten serialiseerbaar zijn.

Aan de andere kant kunnen we gaan nadenken over het lezen en schrijven van regels.

Daarvoor maken we gebruik van OpenCSV:

 com.opencsv opencsv 4.1 

Zoek de nieuwste OpenCSV-versie in Maven Central.

Zodra OpenCSV is inbegrepen, we gaan ook een FileUtils klasse. Het biedt methoden voor het lezen en schrijven van CSV-regels:

openbare klasse FileUtils {openbare regel readLine () genereert uitzondering {if (CSVReader == null) initReader (); String [] line = CSVReader.readNext (); if (line == null) retourneert null; retourneer nieuwe regel (regel [0], LocalDate.parse (regel [1], DateTimeFormatter.ofPattern ("MM / dd / jjjj"))); } public void writeLine (Line line) gooit uitzondering {if (CSVWriter == null) initWriter (); String [] lineStr = nieuwe String [2]; lineStr [0] = line.getName (); lineStr [1] = lijn .getAge () .toString (); CSVWriter.writeNext (lineStr); } // ...}

Let erop dat Lees regel fungeert als een wrapper over OpenCSV's readNext methode en retourneert een Lijn voorwerp.

Zelfde manier, Schrijf lijn wraps OpenCSV's writeNext het ontvangen van een Lijn voorwerp. De volledige implementatie van deze klasse is te vinden in het GitHub-project.

Op dit punt zijn we helemaal klaar om te beginnen met de implementatie van elke stap.

4.4. LinesReader

Laten we doorgaan en onze afmaken LinesReader klasse:

openbare klasse LinesReader implementeert Tasklet, StepExecutionListener {privé laatste Logger-logger = LoggerFactory .getLogger (LinesReader.class); privélijstlijnen; privé FileUtils fu; @Override public void beforeStep (StepExecution stepExecution) {lines = new ArrayList (); fu = nieuwe FileUtils ("taskletsvschunks / input / tasklets-vs-chunks.csv"); logger.debug ("Lines Reader geïnitialiseerd."); } @Override openbare RepeatStatus uitvoeren (StepContribution stepContribution, ChunkContext chunkContext) genereert Uitzondering {Line line = fu.readLine (); while (line! = null) {lines.add (regel); logger.debug ("Lees regel:" + line.toString ()); lijn = fu.readLine (); } return RepeatStatus.FINISHED; } @Override openbare ExitStatus afterStep (StepExecution stepExecution) {fu.closeReader (); stepExecution .getJobExecution () .getExecutionContext () .put ("lines", this.lines); logger.debug ("Lines Reader beëindigd."); retourneer ExitStatus.COMPLETED; }}

LinesReader wordt uitgevoerd methode creëert een FileUtils instantie over het pad van het invoerbestand. Dan, voegt regels toe aan een lijst totdat er geen regels meer zijn om te lezen.

Onze klas implementeert ook StepExecutionListener dat biedt twee extra methoden: beforeStep en afterStep. We zullen deze methoden gebruiken om dingen voor en na te initialiseren en te sluiten uitvoeren loopt.

Als we eens kijken afterStep code, we zullen de regel opmerken waar de resultatenlijst (lijnen) wordt in de context van de job geplaatst om deze beschikbaar te maken voor de volgende stap:

stepExecution .getJobExecution () .getExecutionContext () .put ("lines", this.lines);

Op dit punt heeft onze eerste stap zijn verantwoordelijkheid al vervuld: CSV-lijnen laden in een Lijst in het geheugen. Laten we naar de tweede stap gaan en ze verwerken.

4.5. LinesProcessor

LinesProcessor zal ook implementeren StepExecutionListener en uiteraard, Tasklet. Dat betekent dat het zal implementeren beforeStep, uitvoeren en afterStep methoden ook:

openbare klasse LinesProcessor implementeert Tasklet, StepExecutionListener {privé Logger-logger = LoggerFactory.getLogger (LinesProcessor.class); privélijstlijnen; @Override public void beforeStep (StepExecution stepExecution) {ExecutionContext executionContext = stepExecution .getJobExecution () .getExecutionContext (); this.lines = (Lijst) executionContext.get ("lijnen"); logger.debug ("Lines Processor geïnitialiseerd."); } @Override openbare RepeatStatus uitvoeren (StepContribution stepContribution, ChunkContext chunkContext) genereert uitzondering {voor (Line line: lines) {long age = ChronoUnit.YEARS.between (line.getDob (), LocalDate.now ()); logger.debug ("Berekende leeftijd" + leeftijd + "voor regel" + line.toString ()); line.setAge (leeftijd); } return RepeatStatus.FINISHED; } @Override openbare ExitStatus afterStep (StepExecution stepExecution) {logger.debug ("Lines Processor beëindigd."); retourneer ExitStatus.COMPLETED; }}

Het is moeiteloos om dat te begrijpen het laadt lijnen lijst uit de context van de baan en berekent de leeftijd van elke persoon.

Het is niet nodig om nog een resultatenlijst in de context te plaatsen, aangezien er wijzigingen plaatsvinden op hetzelfde object dat afkomstig is uit de vorige stap.

En we zijn klaar voor onze laatste stap.

4.6. LinesWriter

LinesWriterHet is de taak om eroverheen te gaan lijnen list en schrijf naam en leeftijd naar het uitvoerbestand:

openbare klasse LinesWriter implementeert Tasklet, StepExecutionListener {privé laatste Logger-logger = LoggerFactory .getLogger (LinesWriter.class); privélijstlijnen; privé FileUtils fu; @Override public void beforeStep (StepExecution stepExecution) {ExecutionContext executionContext = stepExecution .getJobExecution () .getExecutionContext (); this.lines = (Lijst) executionContext.get ("lijnen"); fu = nieuwe FileUtils ("output.csv"); logger.debug ("Lines Writer geïnitialiseerd."); } @Override openbare RepeatStatus uitvoeren (StepContribution stepContribution, ChunkContext chunkContext) genereert uitzondering {voor (Line line: lines) {fu.writeLine (line); logger.debug ("Regel geschreven" + line.toString ()); } return RepeatStatus.FINISHED; } @Override openbare ExitStatus afterStep (StepExecution stepExecution) {fu.closeWriter (); logger.debug ("Lines Writer beëindigd."); retourneer ExitStatus.COMPLETED; }}

We zijn klaar met de uitvoering van ons werk! Laten we een test maken om deze uit te voeren en de resultaten te zien.

4.7. De taak uitvoeren

Om de taak uit te voeren, maken we een test:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (klassen = TaskletsConfig.class) openbare klasse TaskletsTest {@Autowired privé JobLauncherTestUtils jobLauncherTestUtils; @Test openbare ongeldige gegevenTaskletsJob_whenJobEnds_thenStatusCompleted () gooit uitzondering {JobExecution jobExecution = jobLauncherTestUtils.launchJob (); assertEquals (ExitStatus.COMPLETED, jobExecution.getExitStatus ()); }}

ContextConfiguration annotatie verwijst naar de Spring-contextconfiguratieklasse, die onze taakdefinitie heeft.

We moeten een paar extra bonen toevoegen voordat we de test uitvoeren:

@Bean openbare JobLauncherTestUtils jobLauncherTestUtils () {retourneer nieuwe JobLauncherTestUtils (); } @Bean openbare JobRepository jobRepository () gooit uitzondering {MapJobRepositoryFactoryBean factory = nieuwe MapJobRepositoryFactoryBean (); factory.setTransactionManager (transactionManager ()); return (JobRepository) factory.getObject (); } @Bean public PlatformTransactionManager transactionManager () {retourneer nieuwe ResourcelessTransactionManager (); } @Bean openbare JobLauncher jobLauncher () gooit uitzondering {SimpleJobLauncher jobLauncher = nieuwe SimpleJobLauncher (); jobLauncher.setJobRepository (jobRepository ()); terug jobLauncher; }

Alles is klaar! Ga je gang en voer de test uit!

Nadat de klus is geklaard, output.csv heeft de verwachte inhoud en logboeken tonen de uitvoeringsstroom:

[main] DEBUG o.b.t.tasklets.LinesReader - Lines Reader geïnitialiseerd. [main] DEBUG obttasklets.LinesReader - Regel lezen: [Mae Hodges, 22/10/1972] [main] DEBUG obttasklets.LinesReader - Regel lezen: [Gary Potter, 22/02/1953] [main] DEBUG obttasklets .LinesReader - Regel lezen: [Betty Wise, 17/02/1968] [hoofd] DEBUG obttasklets.LinesReader - Regel lezen: [Wayne Rose, 04/06/1977] [hoofd] DEBUG obttasklets.LinesReader - Regel lezen: [Adam Caldwell, 27/09/1995] [main] DEBUG obttasklets.LinesReader - Regel lezen: [Lucille Phillips, 14/05/1992] [main] DEBUG obttasklets.LinesReader - Lines Reader is beëindigd. [main] DEBUG o.b.t.tasklets.LinesProcessor - Lines Processor geïnitialiseerd. [main] DEBUG obttasklets.LinesProcessor - Berekende leeftijd 45 voor regel [Mae Hodges, 10/22/1972] [main] DEBUG obttasklets.LinesProcessor - Berekende leeftijd 64 voor regel [Gary Potter, 02/22/1953] [main ] DEBUG obttasklets.LinesProcessor - Berekende leeftijd 49 voor regel [Betty Wise, 02/17/1968] [hoofd] DEBUG obttasklets.LinesProcessor - Berekende leeftijd 40 voor regel [Wayne Rose, 04/06/1977] [hoofd] DEBUG obttasklets.LinesProcessor - Berekende leeftijd 22 voor regel [Adam Caldwell, 27/09/1995] [hoofd] DEBUG obttasklets.LinesProcessor - Berekende leeftijd 25 voor regel [Lucille Phillips, 05/14/1992] [hoofd] DEBUG obttasklets .LinesProcessor - Lines Processor is beëindigd. [main] DEBUG o.b.t.tasklets.LinesWriter - Lines Writer geïnitialiseerd. [main] DEBUG obttasklets.LinesWriter - schreef regel [Mae Hodges, 22/10/1972,45] [main] DEBUG obttasklets.LinesWriter - schreef regel [Gary Potter, 22/02 / 1953,64] [main] DEBUG obttasklets.LinesWriter - Schreef regel [Betty Wise, 02/17 / 1968,49] [main] DEBUG obttasklets.LinesWriter - Schreef regel [Wayne Rose, 04/06 / 1977,40] [main] DEBUG obttasklets.LinesWriter - Regel geschreven [Adam Caldwell, 27/09/1995,22] [hoofd] DEBUG obttasklets.LinesWriter - Regel geschreven [Lucille Phillips, 14/05/1992,25] [hoofd] DEBUG obttasklets.LinesWriter - Regels Writer beëindigd .

Dat is het voor Tasklets. Nu kunnen we verder gaan met de Chunks-benadering.

5. Brokken aanpak

5.1. Inleiding en ontwerp

Zoals de naam suggereert, deze aanpak voert acties uit over brokken gegevens. Dat wil zeggen, in plaats van alle regels tegelijk te lezen, te verwerken en te schrijven, zal het een vast aantal records (chunk) per keer lezen, verwerken en schrijven.

Vervolgens herhaalt het de cyclus totdat er geen gegevens meer in het bestand staan.

Als gevolg hiervan zal de stroom iets anders zijn:

  1. Hoewel er regels zijn:
    • Doe voor X aantal regels:
      • Lees een regel
      • Verwerk één regel
    • Schrijf X aantal regels.

We moeten dus ook creëren drie bonen voor brokgeoriënteerde aanpak:

openbare klasse LineReader {// ...}
openbare klasse LineProcessor {// ...}
openbare klasse LinesWriter {// ...}

Laten we onze taak configureren voordat we overgaan tot implementatie.

5.2. Configuratie

De functieomschrijving zal er ook anders uitzien:

@Configuration @EnableBatchProcessing openbare klasse ChunksConfig {@Autowired privé JobBuilderFactory-taken; @Autowired private StepBuilderFactory stappen; @Bean openbare ItemReader itemReader () {retourneer nieuwe LineReader (); } @Bean public ItemProcessor itemProcessor () {retourneer nieuwe LineProcessor (); } @Bean public ItemWriter itemWriter () {retourneer nieuwe LinesWriter (); } @Bean beschermde Step processLines (ItemReader-lezer, ItemProcessor-processor, ItemWriter-schrijver) {return steps.get ("processLines"). chunk (2) .reader (lezer) .processor (processor) .writer (schrijver) .build (); } @Bean openbare Job job () {retourneer jobs .get ("chunksJob") .start (processLines (itemReader (), itemProcessor (), itemWriter ())) .build (); }}

In dit geval is er slechts één stap die slechts één taaklet uitvoert.

Die tasklet definieert een lezer, een schrijver en een processor die zullen handelen over brokken gegevens.

Merk op dat de commit-interval geeft de hoeveelheid gegevens aan die in één stuk moeten worden verwerkt. Onze taak zal twee regels tegelijk lezen, verwerken en schrijven.

Nu zijn we klaar om onze broklogica toe te voegen!

5.3. LineReader

LineReader zal verantwoordelijk zijn voor het lezen van één record en het retourneren van een Lijn instantie met zijn inhoud.

Om een ​​lezer te worden, onze klas moet implementeren ItemReader koppel:

public class LineReader implementeert ItemReader {@Override public Line read () genereert uitzondering {Line line = fu.readLine (); if (line! = null) logger.debug ("Read line:" + line.toString ()); retourlijn; }}

De code is eenvoudig, hij leest slechts één regel en retourneert deze. We zullen ook implementeren StepExecutionListener voor de definitieve versie van deze klasse:

openbare klasse LineReader implementeert ItemReader, StepExecutionListener {privé laatste Logger-logger = LoggerFactory .getLogger (LineReader.class); privé FileUtils fu; @Override public void beforeStep (StepExecution stepExecution) {fu = new FileUtils ("taskletsvschunks / input / tasklets-vs-chunks.csv"); logger.debug ("Line Reader geïnitialiseerd."); } @Override public Line read () gooit uitzondering {Line line = fu.readLine (); if (line! = null) logger.debug ("Read line:" + line.toString ()); retourlijn; } @Override openbare ExitStatus afterStep (StepExecution stepExecution) {fu.closeReader (); logger.debug ("Lijnlezer beëindigd."); retourneer ExitStatus.COMPLETED; }}

Dat moet worden opgemerkt beforeStep en afterStep respectievelijk voor en na de hele stap uitvoeren.

5.4. LineProcessor

LineProcessor volgt vrijwel dezelfde logica dan LineReader.

In dit geval we zullen implementeren ItemProcessor en zijn methode werkwijze():

openbare klasse LineProcessor implementeert ItemProcessor {privé Logger-logger = LoggerFactory.getLogger (LineProcessor.class); @Override public Line-proces (Line-regel) genereert Uitzondering {long age = ChronoUnit.YEARS .between (line.getDob (), LocalDate.now ()); logger.debug ("Berekende leeftijd" + leeftijd + "voor regel" + line.toString ()); line.setAge (leeftijd); retourlijn; }}

De werkwijze() methode neemt een invoerregel, verwerkt deze en retourneert een uitvoerregel. Nogmaals, we zullen ook implementeren StepExecutionListener:

openbare klasse LineProcessor implementeert ItemProcessor, StepExecutionListener {privé Logger-logger = LoggerFactory.getLogger (LineProcessor.class); @Override public void beforeStep (StepExecution stepExecution) {logger.debug ("Line Processor geïnitialiseerd."); } @Override public Line-proces (Line-regel) genereert Uitzondering {long age = ChronoUnit.YEARS .between (line.getDob (), LocalDate.now ()); logger.debug ("Berekende leeftijd" + leeftijd + "voor regel" + line.toString ()); line.setAge (leeftijd); retourlijn; } @Override openbare ExitStatus afterStep (StepExecution stepExecution) {logger.debug ("Lijnprocessor beëindigd."); retourneer ExitStatus.COMPLETED; }}

5.5. LinesWriter

In tegenstelling tot lezer en processor, LinesWriter zal een heel stuk regels schrijven zodat het een Lijst van Lijnen:

openbare klasse LinesWriter implementeert ItemWriter, StepExecutionListener {privé laatste Logger-logger = LoggerFactory .getLogger (LinesWriter.class); privé FileUtils fu; @Override public void beforeStep (StepExecution stepExecution) {fu = new FileUtils ("output.csv"); logger.debug ("Line Writer geïnitialiseerd."); } @Override public void write (List lines) gooit uitzondering {for (Line line: lines) {fu.writeLine (line); logger.debug ("Regel geschreven" + line.toString ()); }} @Override openbare ExitStatus afterStep (StepExecution stepExecution) {fu.closeWriter (); logger.debug ("Line Writer beëindigd."); retourneer ExitStatus.COMPLETED; }}

LinesWriter code spreekt voor zich. En nogmaals, we zijn klaar om ons werk te testen.

5.6. De taak uitvoeren

We zullen een nieuwe test maken, dezelfde als degene die we hebben gemaakt voor de tasklets-benadering:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (klassen = ChunksConfig.class) openbare klasse ChunksTest {@Autowired privé JobLauncherTestUtils jobLauncherTestUtils; @Test openbare ongeldig gegevenChunksJob_whenJobEnds_thenStatusCompleted () gooit uitzondering {JobExecution jobExecution = jobLauncherTestUtils.launchJob (); assertEquals (ExitStatus.COMPLETED, jobExecution.getExitStatus ()); }}

Na het configureren ChunksConfig zoals hierboven uitgelegd voor TaskletsConfig, we zijn helemaal klaar om de test uit te voeren!

Als de klus eenmaal is geklaard, kunnen we dat zien output.csv bevat opnieuw het verwachte resultaat en de logboeken beschrijven de stroom:

[main] DEBUG o.b.t.chunks.LineReader - Line Reader geïnitialiseerd. [main] DEBUG o.b.t.chunks.LinesWriter - Line Writer geïnitialiseerd. [main] DEBUG o.b.t.chunks.LineProcessor - Lijnprocessor geïnitialiseerd. [main] DEBUG obtchunks.LineReader - Regel lezen: [Mae Hodges, 22/10/1972] [main] DEBUG obtchunks.LineReader - Regel lezen: [Gary Potter, 22/02/1953] [main] DEBUG obtchunks .LineProcessor - Berekende leeftijd 45 voor regel [Mae Hodges, 22/10/1972] [hoofd] DEBUG obtchunks.LineProcessor - Berekende leeftijd 64 voor regel [Gary Potter, 22/02/1953] [hoofd] DEBUG obtchunks.LinesWriter - Regel schrijven [Mae Hodges, 22/10/1972,45] [hoofd] DEBUG obtchunks.LinesWriter - Regel schrijven [Gary Potter, 22/22 / 1953,64] [hoofd] DEBUG obtchunks.LineReader - Regel lezen: [Betty Wise, 17/02/1968] [hoofd] DEBUG obtchunks.LineReader - Regel lezen: [Wayne Rose, 04/06/1977] [hoofd] DEBUG obtchunks.LineProcessor - Berekende leeftijd 49 voor regel [Betty Wise, 17/02/1968] [main] DEBUG obtchunks.LineProcessor - Berekende leeftijd 40 voor regel [Wayne Rose, 04/06/1968] [main] DEBUG obtchunks.LinesWriter - Regel geschreven [Betty Wise, 17/02/1968 , 49] [main] DEBUG obtchunks.LinesWriter - Regel geschreven [Wayne Rose, 04/06 / 1977,40] [main] DEBUG ob t.chunks.LineReader - Regel lezen: [Adam Caldwell, 27/09/1995] [main] DEBUG obtchunks.LineReader - Regel lezen: [Lucille Phillips, 14/05/1992] [main] DEBUG obtchunks.LineProcessor - Berekende leeftijd 22 voor regel [Adam Caldwell, 09/27/1995] [hoofd] DEBUG obtchunks.LineProcessor - Berekende leeftijd 25 voor regel [Lucille Phillips, 05/14/1992] [hoofd] DEBUG obtchunks.LinesWriter - Schreef regel [Adam Caldwell, 27/09/1995,22] [main] DEBUG obtchunks.LinesWriter - Regel geschreven [Lucille Phillips, 05/14 / 1992,25] [main] DEBUG obtchunks.LineProcessor - Line Processor beëindigd. [main] DEBUG o.b.t.chunks.LinesWriter - Line Writer is beëindigd. [main] DEBUG o.b.t.chunks.LineReader - Line Reader is beëindigd.

We hebben hetzelfde resultaat en een andere stroom. Logboeken maken duidelijk hoe de taak volgens deze aanpak wordt uitgevoerd.

6. Conclusie

Verschillende contexten zullen de behoefte aan de ene of de andere benadering aantonen. Hoewel Tasklets natuurlijker aanvoelen voor ‘de ene taak na de andere'-scenario's, bieden chunks een eenvoudige oplossing voor gepagineerde leesopdrachten of situaties waarin we geen aanzienlijke hoeveelheid gegevens in het geheugen willen bewaren.

De volledige implementatie van dit voorbeeld is te vinden in het GitHub-project.


$config[zx-auto] not found$config[zx-overlay] not found