You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何让JobScheduler调度的多任务按设定延迟依次执行?

看起来你是在用Android的JobScheduler处理任务,但遇到了多任务并行执行不符合需求的问题——想要让它们按各自设定的延迟逐个串行运行对吧?我之前也处理过类似的场景,给你分享一个可行的方案:

核心思路是用一个全局单例的任务管理器来维护所有待执行的任务队列,确保同一时间只有一个任务在运行(包括等待延迟的过程),前一个任务完全执行完毕后再启动下一个。这样就能严格控制任务的执行顺序,不会出现并行的情况。

具体实现步骤:

1. 实现单例的TaskManager(任务管理器)

这个类负责维护任务队列、控制任务的串行执行,保证线程安全:

public class TaskManager {
    private static TaskManager instance;
    private final Queue<JobParameters> taskQueue = new LinkedList<>();
    private boolean isProcessing = false;

    private TaskManager() {}

    public static synchronized TaskManager getInstance() {
        if (instance == null) {
            instance = new TaskManager();
        }
        return instance;
    }

    public synchronized void addTask(JobParameters jobParams) {
        taskQueue.add(jobParams);
        // 如果当前没有任务在处理,立即启动第一个任务
        if (!isProcessing) {
            processNextTask();
        }
    }

    private synchronized void processNextTask() {
        if (taskQueue.isEmpty()) {
            isProcessing = false;
            return;
        }
        isProcessing = true;
        JobParameters currentJob = taskQueue.poll();
        
        new Thread(() -> {
            // 获取当前任务的延迟时间
            PersistableBundle extras = currentJob.getExtras();
            int delay = extras.getInt("delay", 0);
            Log.d("Time", "Waiting for " + delay + "ms before executing job " + currentJob.getJobId());
            
            // 等待设定的延迟时间
            try {
                Thread.sleep(delay);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                Log.e("TaskManager", "Task interrupted", e);
            }

            // --------------------------
            // 这里写你的任务业务逻辑
            // 比如处理数据、网络请求等
            Log.d("TaskManager", "Executing job " + currentJob.getJobId());
            // --------------------------

            // 任务执行完成,通知JobService任务结束
            MyJobService.notifyJobFinished(currentJob, false);

            // 启动下一个任务
            processNextTask();
        }).start();
    }
}

2. 修改你的JobService实现

让JobService不再直接执行任务,而是把任务交给TaskManager管理:

public class MyJobService extends JobService {
    private static WeakReference<MyJobService> serviceRef;

    @Override
    public void onCreate() {
        super.onCreate();
        serviceRef = new WeakReference<>(this);
    }

    @Override
    public boolean onStartJob(final JobParameters jobParameters) {
        // 将任务加入全局队列,由TaskManager控制串行执行
        TaskManager.getInstance().addTask(jobParameters);
        // 返回true表示任务会在后台继续执行,之后需要调用jobFinished
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters jobParameters) {
        // 如果任务被系统强制停止,返回true表示需要重新调度(根据你的需求调整)
        return true;
    }

    // 提供静态方法让TaskManager调用,通知任务完成
    public static void notifyJobFinished(JobParameters jobParams, boolean needsReschedule) {
        MyJobService service = serviceRef != null ? serviceRef.get() : null;
        if (service != null) {
            service.jobFinished(jobParams, needsReschedule);
        }
    }
}

3. 别忘了在Manifest中注册JobService

<service
    android:name=".MyJobService"
    android:permission="android.permission.BIND_JOB_SERVICE" />

关键说明:

  • 线程安全:TaskManager的方法都用synchronized修饰,避免多线程操作队列时出现问题。
  • 串行执行:每次只有一个任务在处理(包括等待延迟的阶段),前一个任务执行完才会启动下一个。
  • 内存安全:用WeakReference保存JobService实例,避免因为长期持有引用导致内存泄漏。
  • 灵活性:每个任务可以携带自己的延迟时间,TaskManager会严格按照队列顺序,每个任务等待自己的延迟后再执行。

这样改造后,你调度的多个任务就会按照加入队列的顺序,逐个等待自己设定的延迟时间后执行,不会再出现并行的情况啦!

内容的提问来源于stack exchange,提问作者Ravi Patel

火山引擎 最新活动