首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在给定延迟后按顺序执行的任务调度

在给定延迟后按顺序执行的任务调度
EN

Stack Overflow用户
提问于 2017-11-23 13:42:10
回答 3查看 738关注 0票数 1

我有一堆工作线程,我想在延迟之后依次执行。我希望做到以下几点:

延迟->工作1 ->延迟->工作者2-延迟->工作者3 -> .

我想出了一个解决方案:

代码语言:javascript
运行
复制
long delay = 5;
for(String value : values) {
    WorkerThread workerThread = new WorkerThread(value);
    executorService.schedule(workerThread, delay, TimeUnit.SECONDS);
    delay = delay + 5;
}

在其中创建了executorService,如:

代码语言:javascript
运行
复制
private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

在Java中有其他方法可以用ExecutorService来实现这一点吗?

EN

回答 3

Stack Overflow用户

发布于 2017-11-23 14:48:36

考虑到你的问题,我想出了另一个解决方案。假设值是可以更改的队列。这里有一个可行的解决方案。我修改了您的WorkerThread,并在其中添加了一个回调对象。希望这能有所帮助。

代码语言:javascript
运行
复制
private final Queue<String> values = new LinkedList<>();

private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

private void start() {
    AtomicLong delay = new AtomicLong(5);
    String value = values.poll();

    if (value != null) {
        WorkerThread workerThread = new WorkerThread(value, new OnCompleteCallback() {
            @Override
            public void complete() {
                String valueToProcessNext = values.poll();

                if (valueToProcessNext != null) {
                    executorService.schedule(new WorkerThread(valueToProcessNext, this), delay.addAndGet(5), TimeUnit.SECONDS);
                }
            }
        });
        executorService.schedule(workerThread, delay.get(), TimeUnit.SECONDS);
    }
}

class WorkerThread implements Runnable {

    private final String value;

    private final OnCompleteCallback callback;

    WorkerThread(String value, OnCompleteCallback callback) {
        this.value = value;
        this.callback = callback;
    }

    @Override
    public void run() {
        try {
            System.out.println(value);
        } finally {
            callback.complete();
        }
    }
}

interface OnCompleteCallback {
    void complete();
}
票数 0
EN

Stack Overflow用户

发布于 2017-11-23 22:42:55

如果应该使用ExecutorService,除了您的解决方案之外,什么都不会想到。但是,您可能会发现CompletableFuture更有用,因为它提供了类似的行为,但相对于任务完成而言,它提供了相对于任务完成的延迟,而用于调度的开始。

代码语言:javascript
运行
复制
CompletableFuture<Void> completableFuture = CompletableFuture.completedFuture(null);
String[] values = new String[]{"a", "b", "c"};
for (String value : values) {
    completableFuture
            .thenRun(() -> {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {

                }
            })
            .thenRun(() -> System.out.println(value));
}
completableFuture.get();
票数 0
EN

Stack Overflow用户

发布于 2017-11-24 07:34:48

您可以在每个员工之间使用一个DelayQueue。用这门课装饰你的工人:

代码语言:javascript
运行
复制
public class DelayedTask implements Runnable {

    private final Runnable task;
    private final DelayQueue<Delayed> waitQueue;
    private final DelayQueue<Delayed> followerQueue;

    public DelayedTask(Runnable task, DelayQueue<Delayed> waitQueue, DelayQueue<Delayed> followerQueue) {
        this.task = Objects.requireNonNull(task);
        this.waitQueue = Objects.requireNonNull(waitQueue);
        this.followerQueue = followerQueue;
    }

    @Override
    public void run() {
        try {
            waitQueue.take();
            try {
                task.run();
            } finally {
                if (followerQueue != null) {
                    followerQueue.add(new Delay(3, TimeUnit.SECONDS));
                }
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

和一个简单的延迟实现

代码语言:javascript
运行
复制
class Delay implements Delayed {
    private final long nanos;

    Delay(long amount, TimeUnit unit) {
        this.nanos = TimeUnit.NANOSECONDS.convert(amount, unit) + System.nanoTime();
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(nanos - System.nanoTime(), TimeUnit.NANOSECONDS);
    }

    @Override
    public int compareTo(Delayed other) {
        return Long.compare(nanos, other.getDelay(TimeUnit.NANOSECONDS));
    }
}

允许这种使用:

代码语言:javascript
运行
复制
    ExecutorService executorService = Executors.newFixedThreadPool(1);

// ....

    DelayQueue<Delayed> currentQueue = new DelayQueue<>();
    currentQueue.add(new Delay(3, TimeUnit.SECONDS));
    for (String value : values) {
        DelayedTask delayedTask = new DelayedTask(new WorkerThread(value), currentQueue, currentQueue = new DelayQueue<>());
        executorService.submit(delayedTask);
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47456958

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档