השחלת דגמים בג'אווה

1. הקדמה

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

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

2. חוטים מקומיים

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

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

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

המשמעות היא שבכל פעם שאנחנו משתמשים באחד ממנגנוני ההשחלה הסטנדרטיים בג'אווה, אנו משתמשים בשרשורים מקוריים. זה כולל java.lang. חוט, java.util.concurrent.Executor, java.util.concurrent.ExecutorService, וכולי.

3. חוטים ירוקים

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

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

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

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

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

גרסאות מוקדמות מאוד השתמשו בשרשור ירוק במקום בשרשור מקורי כמודל ההשחלה הרגיל. זה השתנה בג'אווה 1.2 ומאז לא הייתה לכך שום תמיכה ברמת JVM.

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

4. סיבים

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

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

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

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

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

ל- Java אין כרגע תמיכה מובנית בסיבים. קיימות ספריות שיכולות להציג זאת ליישומים שלנו, כולל אך לא רק:

4.1. קוואזאר

Quasar היא ספריית Java שעובדת היטב עם Java ו- Kotlin טהורים ויש לה גרסה חלופית שעובדת עם Clojure.

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

Quasar דורש גם מג'אווה 11 לעבוד כראוי כך שעלול להגביל את היישומים שיכולים להשתמש בו. ניתן להשתמש בגרסאות ישנות יותר ב- Java 8, אך אלו אינן נתמכות באופן פעיל.

4.2. קילים

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

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

4.3. פרויקט נול

Project Loom הוא ניסוי של פרויקט OpenJDK להוסיף סיבים ל- JVM עצמו, ולא כספריית תוספות. זה ייתן לנו את היתרונות של סיבים על פני חוטים. על ידי יישום זה ב- JVM ישירות, זה יכול לעזור במניעת סיבוכים שמציגים סוכני Java ואריגת קוד bytecode.

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

5. שגרות משותפות

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

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

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

6. מסקנה

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


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