ExecutorService - ממתין לסיום החוטים

1. סקירה כללית

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

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

2. אחרי של המוציא לפועל לכבות

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

ניתן להשיג לחכות לשרשורים קיימים כדי להשלים את ביצועם באמצעות awaitTermination () שיטה.

זה חוסם את השרשור עד שכל המשימות מסיימות את הביצוע שלהן או שהגיע הזמן הקצוב שצוין:

חלל ציבורי awaitTerminationAfterShutdown (ExecutorService threadPool) {threadPool.shutdown (); נסה {אם (! threadPool.awaitTermination (60, TimeUnit.SECONDS)) {threadPool.shutdownNow (); }} לתפוס (InterruptedException ex) {threadPool.shutdownNow (); Thread.currentThread (). Interrupt (); }}

3. שימוש CountDownLatch

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

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

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

ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool (10); תפס CountDownLatch = CountDownLatch חדש (2); עבור (int i = 0; i {נסה {// ... latch.countDown ();} לתפוס (InterruptedException e) {Thread.currentThread (). interrupt ();}}); } // המתן לתפס את התפס על ידי שני החוטים הנותרים latch.await ();

4. שימוש להפעיל את כל ()

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

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

ExecutorService WORKER_THREAD_POOL = Executors.newFixedThreadPool (10); רשימה callables = Arrays.asList (חדש DelayedCallable ("חוט מהיר", 100), חדש DelayedCallable ("חוט איטי", 3000)); startProcessingTime = System.currentTimeMillis () ארוך; רשימה עתידיים = WORKER_THREAD_POOL.invokeAll (ניתנים להתקשרות); awaitTerminationAfter Shutdown (WORKER_THREAD_POOL); ארוך totalProcessingTime = System.currentTimeMillis () - startProcessingTime; assertTrue (totalProcessingTime> = 3000); מחרוזת firstThreadResponse = futures.get (0) .get (); assertTrue ("חוט מהיר" .equals (firstThreadResponse)); מחרוזת secondThreadResponse = futures.get (1) .get (); assertTrue ("חוט איטי" .equals (secondThreadResponse));

5. שימוש ExecutorCompletionService

גישה נוספת להפעלת מספר שרשורים היא באמצעות ExecutorCompletionService. הוא משתמש במצורף שירות ExecutorService לביצוע משימות.

הבדל אחד נגמר להפעיל את כל () הוא הסדר שבו ה- עתיד, המייצגים את המשימות שבוצעו מוחזרים. ExecutorCompletionService משתמש בתור כדי לאחסן את התוצאות לפי סדר השלמתן, בזמן להפעיל את כל () מחזירה רשימה עם אותה סדר רציף כמו שהופקה על ידי האיטרטור עבור רשימת המשימות הנתונה:

שירות CompletionService = ExecutorCompletionService חדש (WORKER_THREAD_POOL); רשימה callables = Arrays.asList (חדש DelayedCallable ("חוט מהיר", 100), חדש DelayedCallable ("חוט איטי", 3000); עבור (ניתן להתקשר להתקשרות: להתקשרות) {service.submit (ניתן להתקשר); } 

ניתן לגשת לתוצאות באמצעות לקחת() שיטה:

startProcessingTime = System.currentTimeMillis () ארוך; עתיד עתידי = service.take (); מחרוזת firstThreadResponse = future.get (); ארוך totalProcessingTime = System.currentTimeMillis () - startProcessingTime; assertTrue ("התגובה הראשונה צריכה להיות מהחוט המהיר", "השחלה המהירה" .equals (firstThreadResponse)); assertTrue (totalProcessingTime> = 100 && totalProcessingTime = 3000 && totalProcessingTime <4000); LOG.debug ("החוט הסתיים לאחר:" + totalProcessingTime + "מילישניות"); awaitTerminationAfter Shutdown (WORKER_THREAD_POOL);

6. מסקנה

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

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

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

קוד המקור של המאמר זמין באתר GitHub.


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