You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python轮转调度(Round Robin)模拟异常输出问题:Job3到达时间不符合预期

Python轮转调度(Round Robin)模拟异常输出问题:Job3到达时间不符合预期

嘿,我仔细看了你的代码和问题,核心问题出在事件处理的时机不对——你的代码没有在每次时间推进后及时检查新到达的作业和完成的I/O任务,导致J3的到达被延迟检测了。

问题根源拆解

  1. J3到达检测延迟:当上下文切换把current_time从1推进到2时,你的代码没有立刻调用update_ready_queue()来检查J3(到达时间2),而是直接执行J2的时间片,把current_time跳到3,直到下一次循环开头才触发作业到达检查,这就导致J3的到达日志晚了1个时间单位。
  2. I/O任务处理不及时:原代码只在循环开头处理I/O,时间跳变后没有及时检查I/O是否完成,比如J3本该在2+2=4完成I/O,但因为被延迟到3才加入I/O队列,实际完成时间变成了5。

修复方案

核心思路是:每次current_time发生变化后,必须立即检查新到达的作业和完成的I/O任务,不能等到下一次循环开头才处理。具体要修改这几个地方:

  • 在上下文切换完成后,立刻调用update_ready_queue()和process_io();
  • 在执行完CPU时间片后,立刻调用这两个函数;
  • 在CPU idle时间推进后,同样立刻调用这两个函数;
  • 确保作业到达检查的逻辑能覆盖当前时间点的所有新作业。

修改后的完整代码

jobs = [
    {"name": "J1", "arrival": 0, "burst": [1, 5, 2], "type": ["CPU", "IO", "CPU"], "completion_time": None},
    {"name": "J2", "arrival": 1, "burst": [1, 2], "type": ["CPU", "CPU"], "completion_time": None},
    {"name": "J3", "arrival": 2, "burst": [2, 1], "type": ["IO", "CPU"], "completion_time": None},
]

# Variables for simulation
current_time = 0
ready_queue = []  # Jobs ready for CPU execution
io_queue = []  # Jobs in I/O phase with (job, start_time)
completed_jobs = 0
context_switch = 1  # Time for context switch
quantum = 1  # Time quantum for Round Robin
first = False
# Event log for debugging
event_log = []
arrived_jobs = set()  # Track jobs that have already had their arrival logged

def log_event(time, event):
    """Log events for debugging."""
    event_log.append(f"Time {time}: {event}")

def update_ready_queue():
    """Update ready queue based on job arrival."""
    for job in jobs:
        # Check if the job arrived 
        if job["arrival"] <= current_time and job["name"] not in arrived_jobs:
            arrived_jobs.add(job["name"])  # Mark job as having arrived
            log_event(current_time, f"{job['name']} arrived")

            # If job is starting with CPU burst, add to ready queue
            if job["type"][0] == "CPU":
                ready_queue.append(job)
                log_event(current_time, f"{job['name']} added to ready queue")

            # If job is starting with I/O burst, add to I/O queue
            if job["type"][0] == "IO":
                io_queue.append((job, current_time))
                log_event(current_time, f"{job['name']} moved to I/O queue")

def process_io():
    """Process jobs in the I/O queue."""
    global completed_jobs
    # 遍历副本避免修改列表时出错
    for job, start_time in list(io_queue):  
        elapsed_time = current_time - start_time
        io_burst_time = job["burst"][0]
        
        if elapsed_time >= io_burst_time:  # I/O burst completed
            io_queue.remove((job, start_time))
            job["burst"].pop(0)
            job["type"].pop(0)
            if job["burst"]:
                if job["type"][0] == "CPU":
                    ready_queue.append(job)
                    log_event(current_time, f"{job['name']} completed I/O and added to ready queue")
            else:
                job["completion_time"] = current_time
                completed_jobs += 1
                log_event(current_time, f"{job['name']} completed")

previous_job = None
while completed_jobs < len(jobs):
    # 先处理当前时间点的到达和I/O完成事件
    update_ready_queue()
    process_io()
    
    if ready_queue:
        current_job = ready_queue.pop(0)

        # 处理上下文切换
        if first and previous_job != current_job:
            current_time += context_switch
            log_event(current_time, "Context switch")
            # 上下文切换后时间变化,立即检查新事件
            update_ready_queue()
            process_io()

        # 执行CPU时间片
        burst_time_left = current_job["burst"][0]
        time_to_execute = min(burst_time_left, quantum)

        current_job["burst"][0] -= time_to_execute
        current_time += time_to_execute
        log_event(current_time, f"{current_job['name']} executed for {time_to_execute} time units")
        
        # 执行完时间片后,立即检查新事件
        update_ready_queue()
        process_io()

        # 处理作业后续状态
        if current_job["burst"][0] == 0:
            current_job["burst"].pop(0)
            current_job["type"].pop(0)
            if current_job["burst"]:
                if current_job["type"][0] == "IO":
                    io_queue.append((current_job, current_time))
                    log_event(current_time, f"{current_job['name']} moved to I/O")
            else:
                current_job["completion_time"] = current_time
                completed_jobs += 1
                log_event(current_time, f"{current_job['name']} completed")

        # 如果作业还有CPU burst,放回就绪队列
        if current_job["burst"] and current_job["type"][0] == "CPU":
            ready_queue.append(current_job)
            log_event(current_time, f"{current_job['name']} added back to ready queue")

        previous_job = current_job
        first = True
    else:
        # CPU空闲,时间推进1
        log_event(current_time, "CPU idle")
        current_time += 1
        # 时间推进后立即检查新事件
        update_ready_queue()
        process_io()

# Output 
print("\n".join(event_log))
completion_times = {job["name"]: job["completion_time"] for job in jobs}
print("Completion Times:", completion_times)

修复后的效果

现在J3会在Time2被正确检测到并加入I/O队列,I/O完成时间变成2+2=4,整体执行流程更符合Round Robin的规则。运行后你会看到J3的到达日志正确出现在Time2,核心问题已经解决。

备注:内容来源于stack exchange,提问作者Ace

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 12:23:07