אצווה באביב - משימות מול נתחים

1. הקדמה

Spring Batch מספק שתי דרכים שונות ליישום עבודה: שימוש בחוברות משימות ונתחים.

במאמר זה נלמד כיצד להגדיר וליישם את שתי השיטות באמצעות דוגמה פשוטה מהחיים האמיתיים.

2. תלות

בוא נתחיל ב הוספת התלות הנדרשת:

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

לקבלת הגרסה העדכנית ביותר של אביב-אצווה-ליבת ובדיקת אצווה-קפיץ, עיין ב- Maven Central

3. מקרה השימוש שלנו

בואו ניקח בחשבון קובץ CSV עם התוכן הבא:

מיי הודג'ס, 10/22/1972 גארי פוטר, 02/22/1953 בטי וויז, 02/17/1968 וויין רוז, 04/06/1977 אדם קלדוול, 27/09/1995 לוסיל פיליפס, 05/14/1992

ה המיקום הראשון של כל שורה מייצג את שמו של האדם והמיקום השני מייצג את תאריך לידתו.

מקרה השימוש שלנו הוא כדי ליצור קובץ CSV נוסף המכיל את שמו וגילו של כל אדם:

מיי הודג'ס, גארי פוטר 45, בטי וויז 64, וויין רוז, 40 אדם קלדוול, 22 לוסיל פיליפס, 25

כעת, כאשר התחום שלנו ברור, בואו ונבנה פיתרון בשתי הגישות. נתחיל עם משימות משימות.

4. גישת משימות

4.1. מבוא ועיצוב

משימות מטלה נועדו לבצע משימה אחת בתוך שלב. התפקיד שלנו יורכב מכמה שלבים שמבוצעים בזה אחר זה. על כל שלב לבצע משימה מוגדרת אחת בלבד.

התפקיד שלנו יורכב משלושה שלבים:

  1. קרא שורות מקובץ CSV הקלט.
  2. חשב את הגיל עבור כל אדם בקובץ CSV הקלט.
  3. כתוב שם וגיל של כל אדם לקובץ CSV חדש.

עכשיו, כשהתמונה הגדולה מוכנה, בואו ליצור כיתה אחת לכל שלב.

LinesReader יהיה אחראי על קריאת נתונים מקובץ הקלט:

מחלקה ציבורית LinesReader מיישמת משימה {// ...}

LinesProcessor יחשב את הגיל עבור כל אדם בתיק:

מחלקה ציבורית LinesProcessor מיישמת משימה {// ...}

סוף כל סוף, LinesWriter תהיה האחריות לכתוב שמות וגילאים לקובץ פלט:

מחלקה ציבורית LinesWriter מיישמת משימה {// ...}

בנקודה זו, כל הצעדים שלנו מיישמים מטלה מִמְשָׁק. זה יאלץ אותנו ליישם את זה לבצע שיטה:

@Override פומבי לבצע RepeatStatus (StepContribution stepContribution, ChunkContext chunkContext) זורק חריג {// ...}

בשיטה זו אנו מוסיפים את ההיגיון עבור כל שלב. לפני שנתחיל בקוד זה, בואו להגדיר את העבודה שלנו.

4.2. תְצוּרָה

אנחנו צריכים הוסף תצורה כלשהי להקשר היישום של Spring. לאחר הוספת הצהרת שעועית רגילה לשיעורים שנוצרו בסעיף הקודם, אנו מוכנים ליצור את הגדרת התפקיד שלנו:

@Configuration @EnableBatchProcessing מחלקה ציבורית TaskletsConfig {@ עבודות פרטיות JobBuilderFactory פרטיות; צעדים StepBuilderFactory פרטיים אוטומטיים; @Bean מוגן Step readLines () {צעדים להחזיר .get ("readLines") .tasklet (linesReader ()) .build (); } @Bean מוגן Step processLines () {צעדים להחזיר .get ("processLines"). משימה (linesProcessor ()) .build (); } @Bean מוגן Step writeLines () {צעדים להחזיר .get ("writeLines"). משימה (linesWriter ()) .build (); } @ משרת משרה ציבורית () משרות (להחזיר משרות .get ("taskletsJob"). התחל (readLines ()) .next (processLines ()) .next (writeLines ()) .build (); } // ...}

זה אומר ששלנו "TaskletsJob" יורכב משלושה שלבים. הראשון (readLines) יבצע את חבילת המשימות שהוגדרה בשעועית linesReader ולעבור לשלב הבא: processLines. ProcessLines יבצע את החוברת המוגדרת בשעועית קווים מעבד וללכת לשלב הסופי: writeLines.

זרימת העבודה שלנו מוגדרת, ואנחנו מוכנים להוסיף היגיון!

4.3. מודל וכלי עזר

כאשר אנו מתעסקים בשורות בקובץ CSV, אנו ניצור מחלקה קַו:

מחלקה ציבורית מיישמת קו באמצעות Serializable {שם פרטי מחרוזת; פרטי LocalDate dob; פרטית גיל ארוך; // קונסטרוקטור סטנדרטי, גטרים, סטרים ויישום ToString}

שים לב ש קַו מכשירים ניתן לבצע סדרתי. זה בגלל ש קַו ישמש כ- DTO להעברת נתונים בין השלבים. על פי Spring Batch, חפצים המועברים בין השלבים חייבים להיות מסווגים.

מצד שני, אנחנו יכולים להתחיל לחשוב על קריאה וכתיבה של שורות.

לשם כך נשתמש ב- OpenCSV:

 com.opencsv opencsv 4.1 

חפש את הגרסה האחרונה של OpenCSV ב- Maven Central.

לאחר הכללת OpenCSV, אנחנו גם הולכים ליצור FileUtils מעמד. הוא יספק שיטות לקריאה וכתיבה של שורות CSV:

מחלקה ציבורית FileUtils {ציבורי readLine () זורק חריג {אם (CSVReader == null) initReader (); מחרוזת [] שורה = CSVReader.readNext (); אם (line == null) להחזיר null; להחזיר קו חדש (שורה [0], LocalDate.parse (שורה [1], DateTimeFormatter.ofPattern ("MM / dd / yyyy")); } public void writeLine (Line line) זורק Exception {if (CSVWriter == null) initWriter (); מחרוזת [] lineStr = מחרוזת חדשה [2]; lineStr [0] = line.getName (); lineStr [1] = line .getAge () .toString (); CSVWriter.writeNext (lineStr); } // ...}

שים לב ש קריאת שורה משמש כעטפת על פני OpenCSV readNext שיטה ומחזירה א קַו לְהִתְנַגֵד.

אותה הדרך, writeLine עוטף את OpenCSV כתוב הבא מקבל א קַו לְהִתְנַגֵד. יישום מלא של מחלקה זו ניתן למצוא בפרויקט GitHub.

בשלב זה, כולנו אמורים להתחיל בכל יישום צעד.

4.4. LinesReader

בואו נמשיך ונשלים את שלנו LinesReader מעמד:

מחלקה ציבורית LinesReader מיישמת את Tasklet, StepExecutionListener {לוגר לוגר לוגרי פרטי = LoggerFactory .getLogger (LinesReader.class); קווי רשימה פרטיים; FileUtils פרטית פו; @ ביטול ציבורי בטל לפני Step (StepExecution stepExecution) {lines = ArrayList new (); fu = FileUtils חדשים ("taskletsvschunks / input / tasklets-vs-chunks.csv"); logger.debug ("קורא הקווים מאותחל."); } @Override פומבי ביצוע RepeatStatus (StepContribution stepContribution, ChunkContext chunkContext) זורק חריג {Line line = fu.readLine (); ואילו (קו! = null) {שורות.תוסף (שורה); logger.debug ("קרא שורה:" + line.toString ()); קו = fu.readLine (); } להחזיר RepeatStatus.FINISHED; } @Override ExitStatus ציבורי afterStep (StepExecution stepExecution) {fu.closeReader (); stepExecution .getJobExecution () .getExecutionContext () .put ("שורות", this.lines); logger.debug ("קורא השורות הסתיים."); החזר את ExitStatus.COMPLETED; }}

ביצוע LinesReader שיטה יוצרת א FileUtils מופע מעל נתיב קובץ הקלט. לאחר מכן, מוסיף שורות לרשימה עד שאין יותר שורות לקרוא.

הכיתה שלנו גם מיישם StepExecutionListener המספק שתי שיטות נוספות: לפני שלב ו afterStep. נשתמש בשיטות אלה כדי לאתחל ולסגור דברים לפני ואחרי לבצע רץ.

אם נסתכל על לאחר שלב קוד, נבחין בשורה שבה רשימת התוצאות (שורות) מוצב בהקשר של התפקיד כדי להפוך אותו לזמין לשלב הבא:

stepExecution .getJobExecution () .getExecutionContext () .put ("שורות", this.lines);

בשלב זה, הצעד הראשון שלנו כבר מילא את אחריותו: לטעון קווי CSV לתוך רשימה לזכר. בואו נעבור לשלב השני ונעבד אותם.

4.5. LinesProcessor

LinesProcessor גם יישם StepExecutionListener וכמובן, מטלה. זה אומר שזה ייושם לפני שלב, לבצע ו לאחר שלב גם שיטות:

מחלקה ציבורית LinesProcessor מיישמת את Tasklet, StepExecutionListener {לוגר לוגר פרטי = LoggerFactory.getLogger (LinesProcessor.class); קווי רשימה פרטיים; @ ביטול הרווח הציבורי לפני Step (StepExecution stepExecution) {ExecutionContext executionContext = stepExecution .getJobExecution () .getExecutionContext (); this.lines = (רשימה) executContext.get ("שורות"); logger.debug ("מעבד קווים מאותחל."); } @Override ציבורי לבצע RepeatStatus (StepContribution stepContribution, ChunkContext chunkContext) זורק חריג {עבור (קו שורה: קווים) {long age = ChronoUnit.YEARS.between (line.getDob (), LocalDate.now ()); logger.debug ("גיל מחושב" + גיל + "לשורה" + line.toString ()); line.setAge (גיל); } להחזיר RepeatStatus.FINISHED; } @Override ExitStatus ציבורי afterStep (StepExecution stepExecution) {logger.debug ("מעבד שורות הסתיים."); החזר את ExitStatus.COMPLETED; }}

אין מאמץ להבין זאת זה נטען שורות רשום מהקשר התפקיד ומחשב את הגיל של כל אדם.

אין צורך להכניס רשימת תוצאות נוספת בהקשר כיוון שהשינויים מתרחשים על אותו אובייקט שמגיע מהשלב הקודם.

ואנחנו מוכנים לצעד האחרון שלנו.

4.6. LinesWriter

LinesWriterהמשימה היא לעבור שורות רשום וכתוב שם וגיל לקובץ הפלט:

מחלקה ציבורית LinesWriter מיישמת את Tasklet, StepExecutionListener {לוגר לוגר לוגרי פרטי = LoggerFactory .getLogger (LinesWriter.class); קווי רשימה פרטיים; FileUtils פרטית פו; @ ביטול הרווח הציבורי לפני Step (StepExecution stepExecution) {ExecutionContext executionContext = stepExecution .getJobExecution () .getExecutionContext (); this.lines = (רשימה) executContext.get ("שורות"); fu = FileUtils חדשים ("output.csv"); logger.debug ("אתחול כותב שורות."); } @Override הציבור לבצע RepeatStatus (StepContribution stepContribution, ChunkContext chunkContext) זורק חריג {עבור (שורה שורה: קווים) {fu.writeLine (שורה); logger.debug ("שורה כתבה" + line.toString ()); } להחזיר RepeatStatus.FINISHED; } @Override ExitStatus ציבורי afterStep (StepExecution stepExecution) {fu.closeWriter (); logger.debug ("סופר שורות הסתיים."); החזר את ExitStatus.COMPLETED; }}

סיימנו עם יישום העבודה שלנו! בואו ניצור מבחן כדי להריץ אותו ולראות את התוצאות.

4.7. ניהול העבודה

כדי להפעיל את העבודה, ניצור מבחן:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (classes = TaskletsConfig.class) TaskletsTest בכיתה ציבורית {@ JobLauncherTestUtils פרטי פרטי: JobLauncherTestUtils; @Test הציבור בטל givenTaskletsJob_whenJobEnds_thenStatusCompleted () זורק חריג {JobExecution jobExecution = jobLauncherTestUtils.launchJob (); assertEquals (ExitStatus.COMPLETED, jobExecution.getExitStatus ()); }}

ContextConfiguration ההערה מצביעה על מחלקת תצורת ההקשר של האביב, שמוגדרת בה הגדרת התפקיד שלנו.

נצטרך להוסיף כמה שעועית נוספת לפני שנבצע את הבדיקה:

@Bean JobLauncherTestUtils הציבור JobLauncherTestUtils () {להחזיר JobLauncherTestUtils חדשים (); } @Bean JobRepository הציבור JobRepository () זורק חריג {MapJobRepositoryFactoryBean מפעל = MapJobRepositoryFactoryBean חדש (); factory.setTransactionManager (transactionManager ()); return (JobRepository) factory.getObject (); } @Bean פלטפורמת TransactionManager פלטפורמה ציבורית () {להחזיר ResourcelessTransactionManager חדש (); } @Bean JobLauncher הציבור JobLauncher () זורק חריג {SimpleJobLauncher jobLauncher = SimpleJobLauncher חדש (); jobLauncher.setJobRepository (jobRepository ()); החזר JobLauncher; }

הכל מוכן! קדימה ורוץ את המבחן!

לאחר סיום העבודה, output.csv מכיל את התוכן הצפוי והיומנים מציגים את זרימת הביצוע:

[ראשי] DEBUG o.b.t.tasklets.LinesReader - קורא הקווים מאותחל. [ראשי] DEBUG obttasklets.LinesReader - קרא את השורה: [Mae Hodges, 10/22/1972] [main] DEBUG obttasklets.LinesReader - קרא את השורה: [Gary Potter, 02/22/1953] [main] DEBUG obttasklets .LinesReader - קרא שורה: [בטי ווייז, 02/17/1968] [ראשי] DEBUG obttasklets.LinesReader - קרא שורה: [Wayne Rose, 04/06/1977] [main] DEBUG obttasklets.LinesReader - קרא שורה: [אדם קלדוול, 09/27/1995] [ראשי] DEBUG obttasklets.LinesReader - קרא את השורה: [Lucille Phillips, 05/14/1992] [main] DEBUG obttasklets.LinesReader - קו הקורא הסתיים. [ראשי] DEBUG o.b.t.tasklets.LinesProcessor - מעבד קווים מאותחל. [ראשי] DEBUG obttasklets.LinesProcessor - מחושב גיל 45 לקו [מיי הודג'ס, 22/10/1972] [ראשי] DEBUG obttasklets.LinesProcessor - מחושב גיל 64 עבור קו [גארי פוטר, 22/2/1953] [ראשי ] DEBUG obttasklets.LinesProcessor - מחושב גיל 49 לקו [בטי ווייז, 02/17/1968] [main] DEBUG obttasklets.LinesProcessor - מחושב גיל 40 לקו [Wayne Rose, 04/06/1977] [main] DEBUG obttasklets.LinesProcessor - מחושב גיל 22 לקו [אדם קלדוול, 09/27/1995] [ראשי] DEBUG obttasklets.LinesProcessor - מחושב גיל 25 לקו [Lucille Phillips, 05/14/1992] [main] DEBUG obttasklets .LinesProcessor - מעבד קווים הסתיים. [ראשי] DEBUG o.b.t.tasklets.LinesWriter - כותב שורות מאותחל. [ראשי] DEBUG obttasklets.LinesWriter - כתב שורות [Mae Hodges, 10/22 / 1972,45] [main] DEBUG obttasklets.LinesWriter - Wrote line [Gary Potter, 02/22 / 1953,64] [main] DEBUG obttasklets.LinesWriter - כתבה קו [בטי ווייז, 02/17 / 1968,49] [ראשי] DEBUG obttasklets.LinesWriter - כתבה שורה [וויין רוז, 04/06 / 1977,40] [ראשי] DEBUG obttasklets.LinesWriter - כתב שורה [אדם קלדוול, 09/27 / 1995,22] [ראשי] DEBUG obttasklets.LinesWriter - כתב קו [Lucille Phillips, 05/14 / 1992,25] [main] DEBUG obttasklets.LinesWriter - כותב שורות הסתיים .

זה הכל עבור Tasklets. כעת נוכל לעבור לגישת הנתחים.

5. גישת נתחים

5.1. מבוא ועיצוב

כפי שהשם מרמז, גישה זו מבצע פעולות על פני נתחי נתונים. כלומר, במקום לקרוא, לעבד ולכתוב את כל השורות בבת אחת, הוא יקרא, יעבד ויכתוב כמות קבועה של רשומות (נתח) בכל פעם.

לאחר מכן הוא יחזור על המחזור עד שלא יהיו נתונים נוספים בקובץ.

כתוצאה מכך, הזרימה תהיה שונה במקצת:

  1. אמנם יש שורות:
    • בצע כמות X של קווים:
      • קרא שורה אחת
      • עיבוד שורה אחת
    • כתוב כמות X של שורות.

אז, אנחנו גם צריכים ליצור שלוש שעועית לגישה מכוונת לחתיכות:

LineReader בכיתה ציבורית {// ...}
מחלקה ציבורית LineProcessor {// ...}
מחלקה ציבורית LinesWriter {// ...}

לפני שנעבור ליישום, בואו להגדיר את העבודה שלנו.

5.2. תְצוּרָה

הגדרת התפקיד תראה גם אחרת:

@Configuration @EnableBatchProcessing ChunksConfig בכיתה ציבורית {@ משרות פרטיות JobBuilderFactory פרטיות; צעדים StepBuilderFactory פרטיים אוטומטיים; @Reander ItemReader לציבור itemReader () {להחזיר LineReader חדש (); } @Bean ציבורי ItemProcessor itemProcessor () {להחזיר LineProcessor חדש (); } @Bean ItemWriter ציבורי itemWriter () {להחזיר LinesWriter חדש (); } @Bean מוגן Step processLines (קורא ItemReader, מעבד ItemProcessor, כותב ItemWriter) {return steps.get ("processLines"). נתח (2). קורא (קורא). מעבד (מעבד) .סופר (כותב) .בניין (); } עבודת משרה ציבורית @Bean () {החזרת משרות .get ("chunksJob") .start (processLines (itemReader (), itemProcessor (), itemWriter ())) .build (); }}

במקרה זה, יש רק שלב אחד המבצע משימת עבודה אחת בלבד.

עם זאת, אותה חוברת מגדיר קורא, סופר ומעבד שיפעלו על נתחי נתונים.

שים לב שה- מרווח התחייבות מציין את כמות הנתונים לעיבוד בגוש אחד. העבודה שלנו תקרא, תעבד ותכתוב שתי שורות בכל פעם.

עכשיו אנחנו מוכנים להוסיף את לוגיקת הנתחים שלנו!

5.3. LineReader

LineReader יהיה אחראי על קריאת תקליט אחד והחזרת a קַו מופע עם תוכנו.

כדי להיות קורא, הכיתה שלנו צריכה ליישם ItemReader מִמְשָׁק:

מחלקה ציבורית LineReader מיישמת את ItemReader {@Override Line public read () זורק חריג {Line line = fu.readLine (); אם (line! = null) logger.debug ("קרא שורה:" + line.toString ()); קו חזרה; }}

הקוד פשוט, הוא פשוט קורא שורה אחת ומחזיר אותה. אנחנו גם נבצע StepExecutionListener לגרסה הסופית של שיעור זה:

מחלקה ציבורית LineReader מיישמת את ItemReader, StepExecutionListener {logger logger logger הסופי = LoggerFactory .getLogger (LineReader.class); FileUtils פרטית פו; @ עקוב על החלל הציבורי לפני Step (StepExecution stepExecution) {fu = FileUtils חדשים ("taskletsvschunks / input / tasklets-vs-chunks.csv"); logger.debug ("אות הקורא מאותחל."); } @Override Line public read () זורק חריג {Line line = fu.readLine (); אם (שורה! = null) logger.debug ("קרא את השורה:" + שורה.למחרוזת ()); קו חזרה; } @Override ExitStatus ציבורי afterStep (StepExecution stepExecution) {fu.closeReader (); logger.debug ("קורא השורות הסתיים."); החזר את ExitStatus.COMPLETED; }}

צריך לשים לב לכך לפני שלב ו afterStep לבצע לפני ואחרי כל השלב בהתאמה.

5.4. LineProcessor

LineProcessor עוקב פחות או יותר אחר ההיגיון הזה מאשר LineReader.

עם זאת, במקרה זה, נבצע פריט מעבד ושיטתו תהליך():

מחלקה ציבורית LineProcessor מיישמת את ItemProcessor {לוגר לוגר פרטי = LoggerFactory.getLogger (LineProcessor.class); @Override תהליך קו ציבורי (קו קו) זורק חריג {age age = ChronoUnit.YEARS .between (line.getDob (), LocalDate.now ()); logger.debug ("גיל מחושב" + גיל + "לשורה" + line.toString ()); line.setAge (גיל); קו חזרה; }}

ה תהליך() השיטה לוקחת קו קלט, מעבדת אותה ומחזירה קו פלט. שוב, נבצע גם יישום StepExecutionListener:

מחלקה ציבורית LineProcessor מיישמת ItemProcessor, StepExecutionListener {לוגר לוגר פרטי = LoggerFactory.getLogger (LineProcessor.class); @ ביטול חלל ציבורי לפני Step (StepExecution stepExecution) {logger.debug ("מעבד קו מאותחל."); } @Override תהליך קו ציבורי (קו קו) זורק חריג {age age = ChronoUnit.YEARS .between (line.getDob (), LocalDate.now ()); logger.debug ("גיל מחושב" + גיל + "לשורה" + line.toString ()); line.setAge (גיל); קו חזרה; } @ עקוב על ExitStatus ציבורי לאחר שלב (StepExecution stepExecution) {logger.debug ("מעבד הקו הסתיים."); החזר את ExitStatus.COMPLETED; }}

5.5. LinesWriter

שלא כמו הקורא והמעבד, LinesWriter יכתוב נתח שלם של שורות כך שהוא מקבל א רשימה שֶׁל שורות:

מחלקה ציבורית LinesWriter מיישמת את ItemWriter, StepExecutionListener {private logger logger private = LoggerFactory .getLogger (LinesWriter.class); FileUtils פרטית פו; @ ביטול חלל ציבורי לפני Step (StepExecution stepExecution) {fu = FileUtils חדשים ("output.csv"); logger.debug ("אתחול כותב השורות."); } @ עקוב בטל ציבורי בטל (רשימת שורות) זורק חריג {עבור (שורה שורה: שורות) {fu.writeLine (שורה); logger.debug ("שורה כתבה" + line.toString ()); }} @ עקוב על ExitStatus ציבורי לאחר שלב (StepExecution stepExecution) {fu.closeWriter (); logger.debug ("סופר הקו הסתיים."); החזר את ExitStatus.COMPLETED; }}

LinesWriter קוד מדבר בעד עצמו. ושוב, אנחנו מוכנים לבדוק את העבודה שלנו.

5.6. ניהול העבודה

ניצור מבחן חדש, זהה לזה שיצרנו לגישת משימות המשימות:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (שיעורים = ChunksConfig.class) ChunksTest בכיתה ציבורית {@ JobLauncherTestUtils פרטי פרטי; JobLauncherTestUtils; @Test ציבורי בטל givenChunksJob_whenJobEnds_thenStatusCompleted () זורק חריג {JobExecution jobExecution = jobLauncherTestUtils.launchJob (); assertEquals (ExitStatus.COMPLETED, jobExecution.getExitStatus ()); }}

לאחר הגדרת התצורה ChunksConfig כמוסבר לעיל ל TaskletsConfigכולנו מוכנים להריץ את המבחן

לאחר סיום העבודה נוכל לראות זאת output.csv מכיל שוב את התוצאה הצפויה והיומנים מתארים את הזרימה:

[ראשי] DEBUG o.b.t. chunks.LineReader - קורא הקווים מאותחל. [ראשי] DEBUG o.b.t. chunks.LinesWriter - כותב הקווים מאותחל. [ראשי] DEBUG o.b.t. chunks.LineProcessor - מעבד קו מאותחל. [ראשי] DEBUG obtchunks.LineReader - קרא את השורה: [Ma Hodges, 10/22/1972] [main] DEBUG obtchunks.LineReader - קרא את השורה: [Gary Potter, 02/22/1953] [main] DEBUG obtchunks . LineProcessor - גיל 45 מחושב לקו [מיי הודג'ס, 22/10/1972] [ראשי] DEBUG obtchunks. LineProcessor - מחושב גיל 64 עבור קו [גארי פוטר, 22/22/1953] [main] DEBUG obtchunks.LinesWriter - כתבה שורה [Mae Hodges, 10/22 / 1972,45] [main] DEBUG obtchunks.LinesWriter - Wrote line [Gary Potter, 02/22 / 1953,64] [main] DEBUG obtchunks.LineReader - קרא שורה: [בטי וויז, 02/17/1968] [ראשי] DEBUG obtchunks.LineReader - קרא את השורה: [Wayne Rose, 04/06/1977] [main] DEBUG obtchunks.LineProcessor - מחושב גיל 49 לקו [בטי וויז, 02/17/1968] [ראשי] DEBUG obtchunks.LineProcessor - מחושב גיל 40 לקו [וויין רוז, 04/06/1977] [main] DEBUG obtchunks.LinesWriter - כתב קו [בטי ווייז, 02/17/1968 , 49] [ראשי] DEBUG obtchunks.LinesWriter - כתב שורה [וויין רוז, 04/06 / 1977,40] [ראשי] DEBUG ob t.chunks.LineReader - קרא את השורה: [אדם קלדוול, 09/27/1995] [ראשי] DEBUG obtchunks.LineReader - קרא את השורה: [Lucille Phillips, 05/14/1992] [main] DEBUG obtchunks.LineProcessor - גיל 22 מחושב לקו [אדם קלדוול, 09/27/1995] [ראשי] DEBUG obtchunks.LineProcessor - מחושב גיל 25 לקו [Lucille Phillips, 05/14/1992] [main] DEBUG obtchunks.LinesWriter - קו כתוב [אדם קלדוול, 09/27 / 1995,22] [ראשי] DEBUG obtchunks.LinesWriter - כתב שורה [לוסיל פיליפס, 05/14 / 1992,25] [main] DEBUG obtchunks.LineProcessor - מעבד קו הסתיים. [ראשי] DEBUG o.b.t. chunks.LinesWriter - סופר הקו הסתיים. [ראשי] DEBUG o.b.t. chunks.LineReader - קורא הקווים הסתיים.

יש לנו אותה תוצאה וזרימה אחרת. יומנים מראים כיצד העבודה מתבצעת בעקבות גישה זו.

6. מסקנה

הקשרים שונים יראו את הצורך בגישה זו או אחרת. בעוד ש- Tasklets מרגישים טבעיים יותר לתרחישים של 'משימה אחת אחרי השנייה', נתחים מספקים פיתרון פשוט להתמודדות עם קריאות מדורגות או מצבים שבהם איננו רוצים לשמור בכמות משמעותית של נתונים בזיכרון.

ניתן למצוא את היישום המלא של דוגמה זו ב פרויקט GitHub.


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