מדריך ל- java.lang.Process API

1. הקדמה

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

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

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

2. שימוש תהליך כיתה להרכבת ולהפעלת תוכנית Java

בואו נראה דוגמה להרכיב ולהפעיל תוכנית ג'אווה אחרת בעזרת תהליך ממשק API:

@Test הציבור בטל כאשרExecutedFromAnotherProgram_thenSourceProgramOutput3 () זורק IOException {Process process = Runtime.getRuntime () .exec ("javac -cp src src \ main \ java \ com \ baeldung \ java9 \ process \ OutavaStreamEx "); process = Runtime.getRuntime () .exec ("java -cp src / main / java com.baeldung.java9.process.OutputStreamExample"); פלט BufferedReader = BufferedReader חדש (InputStreamReader חדש (process.getInputStream ())); ערך int = Integer.parseInt (output.readLine ()); assertEquals (3, value); }

לפיכך, היישומים של ביצוע קוד Java בתוך קוד Java קיים הם כמעט בלתי מוגבלים.

3. תהליך יצירת

יישום Java שלנו יכול לפנות לכל יישום הפועל במערכת המחשבים שלנו בכפוף למגבלות מערכת ההפעלה.

לכן אנו יכולים לבצע יישומים. בואו נראה מהם מקרי השימוש השונים שנוכל להריץ על ידי שימוש ב- API של התהליך.

ה ProcessBuilder class מאפשר לנו ליצור תהליכי משנה בתוך היישום שלנו.

בואו נראה הדגמה לפתיחת יישום Notepad מבוסס Windows:

Builder ProcessBuilder = ProcessBuilder חדש ("notepad.exe"); תהליך תהליך = builder.start ();

4. תהליך הרס

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

בואו נראה מקרי שימוש שונים שעל פיהם אפשריים.

4.1. השמדת תהליך לפי הפניה

נניח שאנחנו משתמשים במערכת ההפעלה של Windows ורוצים להוליד את היישום Notepad ולהשמיד אותו.

כמו בעבר, אנו יכולים ליצור מופע של יישום פנקס רשימות באמצעות ה- ProcessBuilder הכיתה וה הַתחָלָה() שיטה.

ואז נוכל להתקשר ל להרוס() שיטה על שלנו תהליך לְהִתְנַגֵד.

4.2. השמדת תהליך לפי תעודת זהות

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

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

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

בואו נראה דוגמה:

Optional optionalProcessHandle = ProcessHandle.of (5232); optionalProcessHandle.ifPresent (processHandle -> processHandle.destroy ()); 

4.3. השמדת תהליך בכוח

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

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

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

אם זה חוזר נכון אז בצע להשמיד בכוח ():

Builder ProcessBuilder = ProcessBuilder חדש ("notepad.exe"); תהליך תהליך = builder.start (); process.destroy (); אם (process.isAlive ()) {process.destroyForcibly (); }

5. ממתין להשלמת תהליך

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

5.1. לחכות ל()

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

בואו נסתכל על הדוגמה:

Builder ProcessBuilder = ProcessBuilder חדש ("notepad.exe"); תהליך תהליך = builder.start (); assertThat (process.waitFor ()> = 0); 

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

5.2. waitfor (זמן רב בחוץ, זמן זמן יחידה)

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

בואו נסתכל על הדוגמה:

Builder ProcessBuilder = ProcessBuilder חדש ("notepad.exe"); תהליך תהליך = builder.start (); assertFalse (process.waitFor (1, TimeUnit.SECONDS));

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

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

6. exitValue ()

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

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

זה יכול להיות כל מספר שלם חיובי אפשרי.

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

@Test הציבורי בטל givenSubProcess_whenCurrentThreadWillNotWaitIndefinitelyforSubProcessToEnd_thenProcessExitValueReturnsGrt0 () זורק IOException {Builder ProcessBuilder = חדש ProcessBuilder ("notepad.exe"); תהליך תהליך = builder.start (); assertThat (process.exitValue ()> = 0); }

7. בחיים()

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

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

בואו נראה דוגמה מהירה לכך:

Builder ProcessBuilder = ProcessBuilder חדש ("notepad.exe"); תהליך תהליך = builder.start (); Thread.sleep (10000); process.destroy (); assertTrue (process.isAlive ());

8. טיפול בזרמי תהליכים

כברירת מחדל, לתהליך המשנה שנוצר אין המסוף או המסוף שלו. כל פעולות ה- I / O הסטנדרטיות שלו (כלומר, stdin, stdout, stderr) יישלחו לתהליך האב. לפיכך תהליך האב יכול להשתמש בזרמים אלה כדי להזין קלט ולקבל פלט מתת-התהליך.

כתוצאה מכך זה נותן לנו כמות עצומה של גמישות מכיוון שהוא נותן לנו שליטה על קלט / פלט של תהליך המשנה שלנו.

8.1. getErrorStream ()

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

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

בואו נראה דוגמה:

@Test הציבור בטל שניתןSubProcess_whenEncounterError_thenErrorStreamNotNull () זורק IOException {Process process = Runtime.getRuntime (). Exec ("javac -cp src src \ main \ java \ com com \ baeldung \ java9 \ תהליך \ תהליך \ "); שגיאת BufferedReader = BufferedReader חדש (InputStreamReader חדש (process.getErrorStream ())); מחרוזת errorString = error.readLine (); assertNotNull (errorString); }

8.2. getInputStream ()

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

@Test הציבור בטל givenSourceProgram_whenReadingInputStream_thenFirstLineEquals3 () זורק IOException {תהליך = Runtime.getRuntime (). Exec ("javac -cp src src \ ראשי \ Java \ com \ baeldung \ java9 \ תהליך \ יציאה "); process = Runtime.getRuntime () .exec ("java -cp src / main / java com.baeldung.java9.process.OutputStreamExample"); פלט BufferedReader = BufferedReader חדש (InputStreamReader חדש (process.getInputStream ())); ערך int = Integer.parseInt (output.readLine ()); assertEquals (3, value); }

8.3. getOutputStream ()

אנו יכולים לשלוח קלט לתהליך משנה מתהליך אב:

סופר w = OutputStreamWriter חדש (process.getOutputStream (), "UTF-8"); w.write ("שלח לילד \ n");

8.4. סינון זרמי תהליכים

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

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

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

@Test הציבור בטל givenRunningProcesses_whenFilterOnProcessIdRange_thenGetSelectedProcessPid () {assertThat (((int) ProcessHandle.allProcesses () .filter (ph -> (ph.pid ()> 10000 && ph.pid () 0);})

9. מסקנה

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

לקריאה נוספת ב- Java 9 Process API, עיין במאמר שלנו כאן.

כמו תמיד, תוכל למצוא את המקורות ב- Github.