本文介绍了如何在一定次数的执行后停止计划重复执行的Runnable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Runnable。我有一个类,使用ScheduledExecutorService调度此Runnable以执行。

I have a Runnable. I have a class that schedules this Runnable for execution using a ScheduledExecutorService with scheduleWithFixedDelay.

我想改变这个类来安排Runnable进行固定延迟执行 无限期,直到它已经运行了一定次数,具体取决于传递给构造函数的一些参数。

I want to alter this class to schedule the Runnable for fixed delay execution either indefinitely, or until it has been run a certain number of times, depending on some parameter that is passed in to the constructor.

如果可能的话,我想使用相同的Runnable,如它在概念上应该是同样的运行。

If possible, I would like to use the same Runnable, as it is conceptually the same thing that should be "run".

有两个Runnables,一个在多个执行后(它保持计数)取消计划,另一个没有:

Have two Runnables, one that cancels the schedule after a number of executions (which it keeps a count of) and one that doesn't:

public class MyClass{
    private ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();

    public enum Mode{
        INDEFINITE, FIXED_NO_OF_TIMES
    }

    public MyClass(Mode mode){
        if(mode == Mode.INDEFINITE){
            scheduler.scheduleWithFixedDelay(new DoSomethingTask(), 0, 100, TimeUnit.MILLISECONDS);
        }else if(mode == Mode.FIXED_NO_OF_TIMES){
            scheduler.scheduleWithFixedDelay(new DoSomethingNTimesTask(), 0, 100, TimeUnit.MILLISECONDS);
        }
    }

    private class DoSomethingTask implements Runnable{
        @Override
        public void run(){
            doSomething();
        }
    }

    private class DoSomethingNTimesTask implements Runnable{
        private int count = 0;

        @Override
        public void run(){
            doSomething();
            count++;
            if(count > 42){
                // Cancel the scheduling.
                // Can you do this inside the run method, presumably using
                // the Future returned by the schedule method? Is it a good idea?
            }
        }
    }

    private void doSomething(){
        // do something
    }
}

我宁愿只有一个Runnable来执行doSomething方法。将调度绑定到Runnable感觉不对。你怎么看?

I would rather just have one Runnable for the execution of the doSomething method. Tying the scheduling to the Runnable feels wrong. What do you think about this?

有一个Runnable用于执行代码我们想要定期运行。有一个单独的调度runnable,用于检查第一个Runnable运行的次数,并在达到一定量时取消。这可能不准确,因为它是异步的。感觉有点麻烦。您如何看待这个?

Have a single Runnable for the execution of the code that we want to run periodically. Have a separate scheduled runnable that checks how many times the first Runnable has run and cancels when it gets to a certain amount. This may not be accurate, as it would be asynchronous. It feels a bit cumbersome. What do you think about this?

扩展ScheduledExecutorService并添加方法scheduleWithFixedDelayNTimes。也许这样的课程已经存在?目前,我正在使用 Executors.newSingleThreadScheduledExecutor(); 来获取我的ScheduledExecutorService实例。我可能必须实现类似的功能来实例化扩展的ScheduledExecutorService。这可能很棘手。您如何看待这个?

Extend ScheduledExecutorService and add a method "scheduleWithFixedDelayNTimes". Perhaps such a class already exists? Currently, I'm using Executors.newSingleThreadScheduledExecutor(); to get my ScheduledExecutorService instance. I would presumably have to implement similar functionality to instantiate the extended ScheduledExecutorService. This could be tricky. What do you think about this?

我无法使用调度程序。我可以改为:

I could not use a scheduler. I could instead have something like:

for(int i = 0; i < numTimesToRun; i++){
    doSomething();
    Thread.sleep(delay);
}

并在某个线程中运行它。你对那个怎么想的?您可能仍然可以使用runnable并直接调用run方法。

And run that in some thread. What do you think of that? You could potentially still use the runnable and call the run method directly.

欢迎任何建议。我正在寻找辩论,找到实现目标的最佳实践方式。

Any suggestions welcome. I'm looking for a debate to find the "best practice" way of achieving my goal.

推荐答案

你可以使用取消关于Future的()方法。来自

You can use the cancel() method on Future. From the javadocs of scheduleAtFixedRate

Otherwise, the task will only terminate via cancellation or termination of the executor

以下是一些包含a的示例代码可在另一个中运行,跟踪原始运行的次数,并在运行N次后取消。

Here is some example code that wraps a Runnable in another that tracks the number of times the original was run, and cancels after running N times.

public void runNTimes(Runnable task, int maxRunCount, long period, TimeUnit unit, ScheduledExecutorService executor) {
    new FixedExecutionRunnable(task, maxRunCount).runNTimes(executor, period, unit);
}

class FixedExecutionRunnable implements Runnable {
    private final AtomicInteger runCount = new AtomicInteger();
    private final Runnable delegate;
    private volatile ScheduledFuture<?> self;
    private final int maxRunCount;

    public FixedExecutionRunnable(Runnable delegate, int maxRunCount) {
        this.delegate = delegate;
        this.maxRunCount = maxRunCount;
    }

    @Override
    public void run() {
        delegate.run();
        if(runCount.incrementAndGet() == maxRunCount) {
            boolean interrupted = false;
            try {
                while(self == null) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        interrupted = true;
                    }
                }
                self.cancel(false);
            } finally {
                if(interrupted) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    }

    public void runNTimes(ScheduledExecutorService executor, long period, TimeUnit unit) {
        self = executor.scheduleAtFixedRate(this, 0, period, unit);
    }
}

这篇关于如何在一定次数的执行后停止计划重复执行的Runnable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 15:36