Who goes next?
When several processes are ready, the scheduler picks one. The simplest rule is a queue — first come, first served — but one long job can make everyone wait. Running the shortest job first minimises the *average* waiting time, at the risk of starving long jobs.
Simulating both
const JOBS = [
{ id: "A", arrival: 0, burst: 8 },
{ id: "B", arrival: 1, burst: 4 },
{ id: "C", arrival: 2, burst: 9 },
{ id: "D", arrival: 3, burst: 5 },
];
function fcfs(jobs) {
const order = [...jobs].sort((a, b) => a.arrival - b.arrival);
let time = 0;
let waiting = 0;
for (const job of order) {
time = Math.max(time, job.arrival); // the CPU may sit idle until it arrives
waiting += time - job.arrival;
time += job.burst;
}
return { order: order.map((j) => j.id), avgWait: waiting / jobs.length };
}
function sjf(jobs) {
const pending = [...jobs];
const order = [];
let time = 0;
let waiting = 0;
while (pending.length) {
const ready = pending.filter((j) => j.arrival <= time);
if (!ready.length) {
time = Math.min(...pending.map((j) => j.arrival));
continue;
}
ready.sort((a, b) => a.burst - b.burst || a.arrival - b.arrival);
const job = ready[0];
pending.splice(pending.indexOf(job), 1);
waiting += time - job.arrival;
order.push(job.id);
time += job.burst;
}
return { order, avgWait: waiting / jobs.length };
}SJF here is *non-preemptive*: once a job starts it runs to the end.