Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 根据任务结果取消计划的固定费率任务_Java_Spring_Scheduled Tasks_Scheduling_Future - Fatal编程技术网

Java 根据任务结果取消计划的固定费率任务

Java 根据任务结果取消计划的固定费率任务,java,spring,scheduled-tasks,scheduling,future,Java,Spring,Scheduled Tasks,Scheduling,Future,我正在使用Spring的TaskScheduler来安排定期任务 ScheduledFuture scheduleAtFixedRate(Runnable task, long period); 我知道我可以在ScheduledFuture上调用cancel(),以停止执行定期任务。但我想根据任务执行的结果取消定期计划任务,但不确定如何最好地执行 ScheduledFuture是否允许我访问每个已执行任务的结果?或者我需要某种任务侦听器来保存对这个ScheduledFuture的引用,并以这种

我正在使用Spring的TaskScheduler来安排定期任务

ScheduledFuture scheduleAtFixedRate(Runnable task, long period);
我知道我可以在ScheduledFuture上调用cancel(),以停止执行定期任务。但我想根据任务执行的结果取消定期计划任务,但不确定如何最好地执行


ScheduledFuture是否允许我访问每个已执行任务的结果?或者我需要某种任务侦听器来保存对这个ScheduledFuture的引用,并以这种方式取消它?还是别的什么?

好吧,看起来这是可能的,但可能有更好的方法

由于周期性作业只接受可运行的(返回类型为void),因此无法返回任务的结果。因此,停止周期性任务的唯一方法是使任务执行副作用,例如,向队列添加停止消息。然后,一个单独的线程需要监视这个队列,一旦看到消息,它就可以取消作业

非常混乱和复杂


更好的替代方法是创建一个常规(一次性)计划任务。然后,任务本身可以决定是否需要安排另一个任务,并可以自己安排下一个任务。

好的,看起来这是可能的,但可能有更好的方法

由于周期性作业只接受可运行的(返回类型为void),因此无法返回任务的结果。因此,停止周期性任务的唯一方法是使任务执行副作用,例如,向队列添加停止消息。然后,一个单独的线程需要监视这个队列,一旦看到消息,它就可以取消作业

非常混乱和复杂


更好的替代方法是创建一个常规(一次性)计划任务。然后,任务本身可以决定是否需要安排另一个任务,并可以自己安排下一个任务。

保留一个句柄或原始固定速率
ScheduledFuture
,然后当出现要取消它的条件时,安排一个执行取消操作的新任务

您还可以使用
可运行的计划未来执行某些操作

来自
ScheduledExecutorService
docs

导入静态java.util.concurrent.TimeUnit.*;
类蜂鸣器控制{
专用最终计划执行器服务计划程序=
Executors.newScheduledThreadPool(1);
公共空间{
最终可运行蜂鸣器=新可运行(){
public void run(){System.out.println(“beep”);}
};
最终计划的未来蜂鸣器手柄=
scheduleAtFixedRate(蜂鸣器,10秒,10秒);
scheduler.schedule(新的Runnable(){
public void run(){beeperHandle.cancel(true);}
},60*60,秒);
}
}

保留一个句柄或原始固定费率
ScheduledFuture
,然后当出现需要取消的情况时,安排一个执行取消操作的新任务

您还可以使用
可运行的计划未来执行某些操作

来自
ScheduledExecutorService
docs

导入静态java.util.concurrent.TimeUnit.*;
类蜂鸣器控制{
专用最终计划执行器服务计划程序=
Executors.newScheduledThreadPool(1);
公共空间{
最终可运行蜂鸣器=新可运行(){
public void run(){System.out.println(“beep”);}
};
最终计划的未来蜂鸣器手柄=
scheduleAtFixedRate(蜂鸣器,10秒,10秒);
scheduler.schedule(新的Runnable(){
public void run(){beeperHandle.cancel(true);}
},60*60,秒);
}
}

下面是一个修改过的蜂鸣器示例,演示了如何在每次计划任务后做出决策。我使用了一个闩锁,这样我就可以将它包装在一个测试用例中,并断言发生了正确的事情(当然还可以防止测试运行者的线程停止)。我还更改了间隔(在最初的10毫秒延迟后,它每10毫秒发出一声蜂鸣声),以便可以在一秒钟内复制、粘贴和执行测试,而不是一小时


import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class BeeperTest {
    class BeeperControl {
        private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, (runnable) -> {
            Thread thread = new Thread(runnable);
            thread.setName("MyAwesomeBeeperTestThread");
            thread.setDaemon(true);
            return thread;
        });

        public void beepTheNumberOfTimesIWant(CountDownLatch latch) {
            long initialDelay = 10;
            long frequency = 10;
            TimeUnit unit = TimeUnit.MILLISECONDS;
            final int numberOfTimesToBeep = 5;
            AtomicInteger numberOfTimesIveBeeped = new AtomicInteger(0);
            final ScheduledFuture[] beeperHandle = new ScheduledFuture[1];
            beeperHandle[0] = scheduler.scheduleAtFixedRate(() -> {
                    if (numberOfTimesToBeep == numberOfTimesIveBeeped.get()) {
                        System.out.println("Let's get this done!");
                        latch.countDown();
                        beeperHandle[0].cancel(false);
                    }
                    else {
                        System.out.println("beep");
                        numberOfTimesIveBeeped.incrementAndGet();
                    }
                }, initialDelay, frequency, unit);
        }
    }

    @Test
    public void beepPlease() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        BeeperControl control = new BeeperControl();
        control.beepTheNumberOfTimesIWant(latch);
        boolean completed = latch.await(1, TimeUnit.SECONDS);
        Assert.assertTrue("Beeper should be able to finish beeping" +
            "within allotted await time.", completed);
    }
}

下面是一个修改后的蜂鸣器示例,演示了如何在每个预定任务之后做出决策。我使用了一个闩锁,这样我就可以将它包装在一个测试用例中,并断言发生了正确的事情(当然还可以防止测试运行者的线程停止)。我还更改了间隔(在最初的10毫秒延迟后,它每10毫秒发出一声蜂鸣声),以便可以在一秒钟内复制、粘贴和执行测试,而不是一小时


import org.junit.Assert;
import org.junit.Test;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class BeeperTest {
    class BeeperControl {
        private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1, (runnable) -> {
            Thread thread = new Thread(runnable);
            thread.setName("MyAwesomeBeeperTestThread");
            thread.setDaemon(true);
            return thread;
        });

        public void beepTheNumberOfTimesIWant(CountDownLatch latch) {
            long initialDelay = 10;
            long frequency = 10;
            TimeUnit unit = TimeUnit.MILLISECONDS;
            final int numberOfTimesToBeep = 5;
            AtomicInteger numberOfTimesIveBeeped = new AtomicInteger(0);
            final ScheduledFuture[] beeperHandle = new ScheduledFuture[1];
            beeperHandle[0] = scheduler.scheduleAtFixedRate(() -> {
                    if (numberOfTimesToBeep == numberOfTimesIveBeeped.get()) {
                        System.out.println("Let's get this done!");
                        latch.countDown();
                        beeperHandle[0].cancel(false);
                    }
                    else {
                        System.out.println("beep");
                        numberOfTimesIveBeeped.incrementAndGet();
                    }
                }, initialDelay, frequency, unit);
        }
    }

    @Test
    public void beepPlease() throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);
        BeeperControl control = new BeeperControl();
        control.beepTheNumberOfTimesIWant(latch);
        boolean completed = latch.await(1, TimeUnit.SECONDS);
        Assert.assertTrue("Beeper should be able to finish beeping" +
            "within allotted await time.", completed);
    }
}

仅供参考,这可能是使用
ScheduledExecutorService
实现的。因此,您可能希望将问题扩大一点,因为它不明确地依赖于spring。仅供参考,这可能是使用
ScheduledExecutorService
实现的。因此,您可能希望将问题扩大一点,因为它不明确地依赖于spring。值得注意的是,此建议并没有真正反映出
scheduleAtFixedRate
的效果,因为它更符合
scheduleWithFixedDelay
的思路。如果您真的想要像OP所问的那样执行
scheduleAtFixedRate
,那么这个答案真的不适合您。你怎么知道?如果您正在运行的任务长于该时间段,并且/或者您不希望任务的执行在重新安排任务之前累积等待任务完成的每次延迟,那么这个建议真的不适用于你。值得注意的是,这个建议并没有真正反映出
scheduleAtFixedRate
的效果,因为它更像是
scheduleatfixeddelay
。如果您真的想要像OP所问的那样执行
scheduleAtFixedRate
,那么这个答案真的不适合您。你怎么知道?如果您正在运行的任务比周期长,和/或您不希望