הגרסה המקדימה של תזמון Shortest Job First (SJF) נקראת Shortest Remaining Time First (SRTF). ב-SRTF, התהליך שנותר לו הזמן הקצר ביותר לסיום נבחר להפעלה. תהליך הריצה נמשך עד שהוא מסתיים או שמגיע תהליך חדש עם זמן שנותר קצר יותר, מה שמבטיח שתהליך הגימור המהיר ביותר תמיד מקבל עדיפות.
דוגמה לאלגוריתם SJF:
תרחיש 1: תהליכים באותו זמן הגעה
דוּגמָה: שקול את הטבלה הבאה של זמן הגעה וזמן פרץ עבור שלושה תהליכים P1 P2 ו-P3 .
| תַהֲלִיך | זמן פרץ | זמן הגעה |
|---|---|---|
| P1 | 6 אלפיות השנייה | 0 אלפיות השנייה |
| P2 | 8 אלפיות השנייה | 0 אלפיות השנייה |
| P3 | 5 אלפיות השנייה | 0 אלפיות השנייה |
ביצוע שלב אחר שלב:
- זמן 0-5 (P3) : P3 פועל למשך 5 אלפיות השנייה (זמן שנותר כולל: 0 אלפיות השנייה) מכיוון שנותר לו את הזמן הקצר ביותר שנותר.
- זמן 5-11 (P1) : P1 פועל למשך 6 אלפיות השנייה (זמן שנותר כולל: 0 אלפיות השנייה) מכיוון שנותר לו את הזמן הקצר ביותר שנותר.
- שעה 11-19 (P2) : P2 פועל למשך 8 אלפיות השנייה (זמן שנותר כולל: 0 אלפיות השנייה) מכיוון שנותר לו את הזמן הקצר ביותר שנותר.
תרשים גאנט:
תפריט הגדרות טלפון אנדרואיד
עכשיו בואו לחשב ממוצע זמן המתנה ולהסתובב זְמַן:
כפי שאנו יודעים
- זמן סיבוב = זמן סיום - זמן הגעה
- זמן המתנה = זמן סיבוב - זמן פרץ
| תַהֲלִיך | זמן הגעה (בְּ) | זמן פרץ מה זה jquery (BT) | זמן השלמה (CT) | זמן סיבוב (TAT) | זמן המתנה (WT) |
|---|---|---|---|---|---|
| P1 | 6 | 11 | 11-0 = 11 | 11-6 = 5 | |
| P2 | מנהל Powershell | 8 | 19 | 19-0 = 19 | 19-8 = 11 |
| P3 | 5 | 5 | 5-0 = 5 | 5-5 = 0 |
עַכשָׁיו
- זמן סיבוב ממוצע = (11 + 19 + 5)/3 = 11.6 אלפיות השנייה
- זמן המתנה ממוצע = (5 + 0 + 11)/3 = 16/3 = 5.33 אלפיות השנייה
תרחיש 2: תהליכים עם זמני הגעה שונים
שקול את הטבלה הבאה של זמן הגעה וזמן פרץ עבור שלושה תהליכים P1 P2 ו-P3.
| תַהֲלִיך | זמן פרץ | זמן הגעה |
|---|---|---|
| P1 | 6 אלפיות השנייה | 0 אלפיות השנייה |
| P2 | 3 אלפיות השנייה | 1 MS |
| P3 | 7 אלפיות השנייה | 2 אלפיות השנייה |
ביצוע שלב אחר שלב:
לתפוס ולנסות ג'אווה
- זמן 0-1 (P1) : P1 פועל למשך 1 ms (זמן שנותר כולל: 5 ms) מכיוון שנותר לו את הזמן הקצר ביותר שנותר.
- זמן 1-4 (P2) : P2 פועל למשך 3 אלפיות השנייה (זמן שנותר כולל: 0 אלפיות השנייה) מכיוון שנותר לו את הזמן הקצר ביותר שנותר בין P1 ו-P2.
- זמן 4-9 (P1) : P1 פועל למשך 5 אלפיות השנייה (זמן שנותר כולל: 0 אלפיות השנייה) מכיוון שנותר לו את הזמן הקצר ביותר שנותר בין P1 ו-P3.
- שעה 9-16 (P3) : P3 פועל למשך 7 אלפיות השנייה (זמן שנותר כולל: 0 אלפיות השנייה) מכיוון שנותר לו את הזמן הקצר ביותר שנותר.
תרשים גאנט:
עכשיו בואו לחשב ממוצע זמן המתנה ולהסתובב זְמַן:
| תַהֲלִיך | זמן הגעה (AT) | זמן פרץ (BT) | זמן השלמה (CT) | זמן סיבוב (TAT) | זמן המתנה (WT) |
|---|---|---|---|---|---|
| P1 | int למחרוזת c++ | 6 | 9 | 9-0 = 9 | 9-6 = 3 |
| P2 | 1 | 3 | 4 | 4-1 = 3 | 3-3 = 0 |
| P3 | 2 | 7 | 16 | 16-2 = 14 | 14-7 = 7 |
- זמן סיבוב ממוצע = (9 + 14 + 3)/3 = 8.6 אלפיות השנייה
- זמן המתנה ממוצע = (3 + 0 + 7)/3 = 10/3 = 3.33 אלפיות השנייה
יישום אלגוריתם SRTF
שלב 1: קלט מספר תהליכים עם זמן הגעה וזמן פרץ.
שלב 2: אתחול הזמנים הנותרים (זמני התפרצות) הזמן הנוכחי = 0 ומונים.
שלב 3: בכל יחידת זמן הוסף תהליכים שהגיעו לתור המוכן.
שלב 4: בחר את התהליך עם הזמן הקצר ביותר שנותר (המנע אם מגיע קצר יותר).
שלב 5: בצע את התהליך שנבחר עבור יחידה 1 צמצם את הזמן הנותר שלה והגדל את הזמן הנוכחי.
שלב 6: אם תהליך מסתיים:
- זמן אספקה = זמן סיום - זמן הגעה
- זמן המתנה = זמן אספקה - זמן פרץ
שלב 7: חזור על שלבים 3-6 עד להשלמת כל התהליכים.
שלב 8: חשב זמן המתנה ממוצע וזמן אספקה.
שלב 9: הצג זמני המתנה והשלמה עבור כל תהליך יחד עם ממוצעים.
יישום קוד
התוכנית ליישום הזמן הקצר ביותר שנותר תחילה היא כדלקמן:
C++#include #include #include using namespace std; struct Process { int id arrivalTime burstTime remainingTime waitingTime turnaroundTime completionTime; }; int main() { int n currentTime = 0 completed = 0; cout << 'Enter number of processes: '; cin >> n; vector<Process> p(n); for (int i = 0; i < n; i++) { p[i].id = i + 1; cin >> p[i].arrivalTime >> p[i].burstTime; p[i].remainingTime = p[i].burstTime; } while (completed < n) { int idx = -1; for (int i = 0; i < n; i++) { if (p[i].arrivalTime <= currentTime && p[i].remainingTime > 0 && (idx == -1 || p[i].remainingTime < p[idx].remainingTime)) { idx = i; } } if (idx != -1) { p[idx].remainingTime--; currentTime++; if (p[idx].remainingTime == 0) { p[idx].completionTime = currentTime; p[idx].turnaroundTime = currentTime - p[idx].arrivalTime; p[idx].waitingTime = p[idx].turnaroundTime - p[idx].burstTime; completed++; } } else { currentTime++; } } double totalWT = 0 totalTAT = 0; for (auto &proc : p) { totalWT += proc.waitingTime; totalTAT += proc.turnaroundTime; cout << 'P' << proc.id << ' CT: ' << proc.completionTime << ' WT: ' << proc.waitingTime << ' TAT: ' << proc.turnaroundTime << endl; } cout << 'Avg WT: ' << totalWT / n << ' Avg TAT: ' << totalTAT / n << endl; }
Java import java.util.*; class Process { int id arrivalTime burstTime remainingTime waitingTime turnaroundTime completionTime; public Process(int id int arrivalTime int burstTime) { this.id = id; this.arrivalTime = arrivalTime; this.burstTime = burstTime; this.remainingTime = burstTime; } } public class SRTF { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); Process[] processes = new Process[n]; for (int i = 0; i < n; i++) { int arrivalTime = sc.nextInt() burstTime = sc.nextInt(); processes[i] = new Process(i + 1 arrivalTime burstTime); } Arrays.sort(processes Comparator.comparingInt(p -> p.arrivalTime)); int currentTime = 0 completed = 0; while (completed < n) { int idx = -1; for (int i = 0; i < n; i++) { if (processes[i].arrivalTime <= currentTime && processes[i].remainingTime > 0 && (idx == -1 || processes[i].remainingTime < processes[idx].remainingTime)) { idx = i; } } if (idx != -1) { processes[idx].remainingTime--; currentTime++; if (processes[idx].remainingTime == 0) { processes[idx].completionTime = currentTime; processes[idx].turnaroundTime = currentTime - processes[idx].arrivalTime; processes[idx].waitingTime = processes[idx].turnaroundTime - processes[idx].burstTime; completed++; } } else { currentTime++; } } double totalWT = 0 totalTAT = 0; for (Process p : processes) { totalWT += p.waitingTime; totalTAT += p.turnaroundTime; System.out.println('P' + p.id + ' CT: ' + p.completionTime + ' WT: ' + p.waitingTime + ' TAT: ' + p.turnaroundTime); } System.out.println('Avg WT: ' + totalWT / n + ' Avg TAT: ' + totalTAT / n); } }
Python class Process: def __init__(self id arrival_time burst_time): self.id = id self.arrival_time = arrival_time self.burst_time = burst_time self.remaining_time = burst_time def srtf(processes): current_time completed = 0 0 while completed < len(processes): idx = -1 for i p in enumerate(processes): if p.arrival_time <= current_time and p.remaining_time > 0 and (idx == -1 or p.remaining_time < processes[idx].remaining_time): idx = i if idx != -1: processes[idx].remaining_time -= 1 current_time += 1 if processes[idx].remaining_time == 0: processes[idx].completion_time = current_time processes[idx].turnaround_time = current_time - processes[idx].arrival_time processes[idx].waiting_time = processes[idx].turnaround_time - processes[idx].burst_time completed += 1 else: current_time += 1 def print_results(processes): total_wt total_tat = 0 0 for p in processes: total_wt += p.waiting_time total_tat += p.turnaround_time print(f'P{p.id} CT: {p.completion_time} WT: {p.waiting_time} TAT: {p.turnaround_time}') print(f'Avg WT: {total_wt / len(processes)} Avg TAT: {total_tat / len(processes)}') n = int(input('Enter number of processes: ')) processes = [Process(i + 1 *map(int input(f'Enter arrival and burst time for P{i + 1}: ').split())) for i in range(n)] srtf(processes) print_results(processes)
תְפוּקָה
Enter number of processes: Avg WT: -nan Avg TAT: -nan
היתרונות של SRTF תזמון
- ממזער את זמן ההמתנה הממוצע : SRTF מקטין את זמן ההמתנה הממוצע על ידי תעדוף תהליכים עם זמן הביצוע הקצר ביותר שנותר.
- יעיל לתהליכים קצרים : תהליכים קצרים יותר מסתיימים מהר יותר ומשפרים את היענות המערכת הכוללת.
- אידיאלי עבור מערכות קריטיות זמן : זה מבטיח שתהליכים רגישים לזמן מבוצעים במהירות.
החסרונות של SRTF תזמון
- הרעבה של תהליכים ארוכים : תהליכים ארוכים יותר עשויים להתעכב ללא הגבלת זמן אם תהליכים קצרים יותר ימשיכו להגיע.
- קשה לחזות זמני פרץ : חיזוי מדויק של זמני התפרצות תהליכים הוא מאתגר ומשפיע על החלטות תזמון.
- תקורה גבוהה : החלפת הקשר תכופה יכולה להגדיל את התקורה ולהאט את ביצועי המערכת.
- לא מתאים למערכות בזמן אמת : משימות בזמן אמת עלולות לסבול עיכובים עקב קדימות תכופות.