הדפיס מספרים זוגיים ומשונים באמצעות 2 אשכולות

1. הקדמה

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

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

2. חוטים בג'אווה

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

מידע נוסף על נושאים ב- Java ניתן למצוא במאמר זה.

ב- Java, אנו יכולים ליצור שרשור על ידי הרחבת ה- פְּתִיל בכיתה או על ידי יישום ה- ניתן לרוץ מִמְשָׁק. בשני המקרים אנו עוקפים את לָרוּץ שיטה וכתוב את יישום החוט בה.

מידע נוסף על אופן השימוש בשיטות אלה ליצירת שרשור ניתן למצוא כאן.

3. סנכרון חוטים

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

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

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

פרטים נוספים על סנכרון חוטים ב- Java ניתן למצוא כאן.

4. תקשורת בין חוטים

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

השיטות בהן נעשה שימוש הן לַחֲכוֹת, לְהוֹדִיעַ, ו להודיע ​​הכל, שכולם עוברים בירושה מה- לְהִתְנַגֵד מעמד.

לַחֲכוֹת() גורם לשרשור הנוכחי להמתין ללא הגבלת זמן עד לכמה שיחות חוט אחרות להודיע ​​() או להודיע ​​() על אותו אובייקט. אנחנו יכולים להתקשר לְהוֹדִיעַ() להעיר חוטים שמחכים לגישה לצג של האובייקט הזה.

ניתן למצוא פרטים נוספים על אופן הפעולה של שיטות אלה כאן.

5. הדפסת מספרים מוזרים ושווים לחלופין

5.1. באמצעות לַחֲכוֹת() ו לְהוֹדִיעַ()

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

בשלב הראשון ניישם את ה- ניתן לרוץ ממשק להגדרת ההיגיון של שני האשכולות. בתוך ה לָרוּץ בשיטה, אנו בודקים אם המספר שווה או אי זוגי.

אם המספר שווה, אנו קוראים ל printEven שיטת ה- מדפסת בכיתה, אחרת אנו מכנים printOdd שיטה:

class TaskEvenOdd מיישמת Runnable {private int max; הדפסת מדפסת פרטית; בוליאני פרטי isEvenNumber; // קונסטרוקטורים סטנדרטיים @ ביטול הפעלה בטלנית ציבורית () {int number = isEvenNumber? 2: 1; בעוד (מספר <= מקסימום) {אם (isEvenNumber) {print.printEven (number); } אחר {print.printOdd (מספר); } מספר + = 2; }}} 

אנו מגדירים את מדפסת כיתה כדלקמן:

מדפסת בכיתה {בוליאני נדיף פרטי isOdd; סרק מסונכרן printEven (int מספר) {תוך (! isOdd) {נסה {wait (); } לתפוס (InterruptedException e) {Thread.currentThread (). interrupt (); }} System.out.println (Thread.currentThread (). GetName () + ":" + מספר); isOdd = שקר; לְהוֹדִיעַ(); } printOdd (int מספר) מסונכרן בטל {בעוד (isOdd) {נסה {wait (); } לתפוס (InterruptedException e) {Thread.currentThread (). interrupt (); }} System.out.println (Thread.currentThread (). GetName () + ":" + מספר); isOdd = נכון; לְהוֹדִיעַ(); }}

בשיטה העיקרית, אנו משתמשים במחלקה המוגדרת כדי ליצור שני שרשורים. אנו יוצרים אובייקט של מדפסת class ולהעביר אותו כפרמטר ל- TaskEvenOdd בַּנַאִי:

סטטי ציבורי ריק ריק (String ... args) {הדפסת מדפסת = מדפסת חדשה (); חוט t1 = חוט חדש (חדש TaskEvenOdd (הדפסה, 10, שקר), "מוזר"); חוט t2 = חוט חדש (חדש TaskEvenOdd (הדפסה, 10, נכון), "אפילו"); t1.start (); t2.start (); }

החוט הראשון יהיה החוט המוזר, ולכן אנו עוברים שֶׁקֶר כערך הפרמטר isEvenNumber. לשרשור השני, אנחנו מעבירים נָכוֹן במקום זאת. הגדרנו את ערך מקסימלי עד 10 עבור שני האשכולות, כך שרק המספרים מ -1 עד 10 מודפסים.

לאחר מכן אנו מתחילים את שני האשכולות בקריאת ה- הַתחָלָה() שיטה. זה יפעיל את לָרוּץ() שיטה של ​​שני הנושאים, כפי שהוגדר לעיל, בה אנו בודקים אם המספר הוא אי זוגי או אפילו ונדפיס אותם.

כאשר החוט המוזר מתחיל לפעול, ערך המשתנה מספר יהיה 1. מכיוון שהוא פחות מ- ערך מקסימלי והדגל isEvenNumber הוא שקר, printOdd () נקרא. בשיטה, אנו בודקים אם הדגל isOdd נכון ובעוד זה נכון אנו קוראים לַחֲכוֹת(). מאז isOdd בהתחלה שקרי, לַחֲכוֹת() לא נקרא, והערך מודפס.

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

אותו תהליך מתבצע עד לערך המשתנה מספר גדול מה- ערך מקסימלי.

5.2. שימוש בסמפורות

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

Java מספקת את סֵמָפוֹר בכיתה ב java.util.concurrent אנו יכולים להשתמש בה כדי ליישם את המנגנון המוסבר. ניתן למצוא פרטים נוספים על סמפורות כאן.

אנו יוצרים שני חוטים, חוט מוזר, וחוט אחיד. החוט המוזר ידפיס את המספרים האי-זוגיים החל מ -1, והחוט האחיד ידפיס את המספרים הזוגיים החל מ -2.

לשני החוטים יש אובייקט של SharedPrinter מעמד. ה SharedPrinter בכיתה יהיו שתי סמפורות, semOdd ו semEven שיהיה להם 1 ו -0 אישורים מלכתחילה. זה יבטיח שמספר אי זוגי יודפס קודם.

יש לנו שתי שיטות printEvenNum () ו printOddNum (). החוט המוזר מכנה את printOddNum () השיטה והחוט האחיד מכנה את printEvenNum () שיטה.

כדי להדפיס מספר אי זוגי, לִרְכּוֹשׁ() השיטה נקראת semOddומכיוון שההיתר הראשוני הוא 1, הוא רוכש את הגישה בהצלחה, מדפיס את המספר האי זוגי והשיחות לְשַׁחְרֵר() עַל semEven.

יִעוּד לְשַׁחְרֵר() יגדיל את ההיתר ב- 1 עבור semEven, ואז השרשור האחיד יכול לרכוש בהצלחה את הגישה ולהדפיס את המספר השווה.

זהו הקוד לתהליך העבודה המתואר לעיל:

main static public void (String [] args) {SharedPrinter sp = SharedPrinter new (); חוט מוזר = חוט חדש (מוזר חדש (sp, 10), "מוזר"); הברגה אחידה = חוט חדש (חדש אפילו (sp, 10), "אפילו"); odd.start (); even.start (); }
מחלקה SharedPrinter {פרטית Semaphore semEven = סמפור חדשה (0); Semaphore פרטי SemOdd = סמפור חדש (1); בטל printEvenNum (int num) {נסה {semEven.acquire (); } לתפוס (InterruptedException e) {Thread.currentThread (). interrupt (); } System.out.println (Thread.currentThread (). GetName () + num); semOdd.release (); } בטל printOddNum (int num) {נסה {semOdd.acquire (); } לתפוס (InterruptedException e) {Thread.currentThread (). interrupt (); } System.out.println (Thread.currentThread (). GetName () + num); semEven.release (); }} מחלקה אפילו מיישמת Runnable {private SharedPrinter sp; פרטיות מקסימום; // קונסטרוקטור סטנדרטי @ הריצה בטלנית ציבורית () {עבור (int i = 2; i <= max; i = i + 2) {sp.printEvenNum (i); }}} יישומים מוזרים בכיתה Runnable {private SharedPrinter sp; פרטיות מקסימום; // קונסטרוקטורים סטנדרטיים @ העבר לרוץ חלל ציבורי () {עבור (int i = 1; i <= max; i = i + 2) {sp.printOddNum (i); }}}

6. מסקנה

במדריך זה בדקנו כיצד אנו יכולים להדפיס מספרים מוזרים ואחידים לחלופין באמצעות שני שרשורים ב- Java. בדקנו שתי שיטות להשגת אותן תוצאות: באמצעות לַחֲכוֹת() ו לְהוֹדִיעַ() ו באמצעות א סֵמָפוֹר.

וכמו תמיד, קוד העבודה המלא זמין ב- GitHub.


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