Java 如何在ScheduledThreadPoolExecutor中停止一个我认为是';完成了

Java 如何在ScheduledThreadPoolExecutor中停止一个我认为是';完成了,java,scheduled-tasks,scheduling,scheduler,Java,Scheduled Tasks,Scheduling,Scheduler,我有一个ScheduledThreadPoolExecutor,我用它来计划以固定速率运行的任务。我希望任务以指定的延迟运行最多10次,直到“成功”。在那之后,我不希望任务被重试。因此,基本上,当我希望停止调度任务时,我需要停止运行该任务,但不需要关闭ScheduledThreadPoolExecutor。知道我该怎么做吗 这里有一些伪代码- public class ScheduledThreadPoolExecutorTest { public static ScheduledThrea

我有一个ScheduledThreadPoolExecutor,我用它来计划以固定速率运行的任务。我希望任务以指定的延迟运行最多10次,直到“成功”。在那之后,我不希望任务被重试。因此,基本上,当我希望停止调度任务时,我需要停止运行该任务,但不需要关闭ScheduledThreadPoolExecutor。知道我该怎么做吗

这里有一些伪代码-

public class ScheduledThreadPoolExecutorTest
{
  public static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(15);  // no multiple instances, just one to serve all requests

  class MyTask implements Runnable
  {
    private int MAX_ATTEMPTS = 10;
    public void run()
    {
      if(++attempt <= MAX_ATTEMPTS)
      {
        doX();
        if(doXSucceeded)
        {
          //stop retrying the task anymore
        }
      }
      else
      { 
        //couldn't succeed in MAX attempts, don't bother retrying anymore!
      }
    }
  }

  public void main(String[] args)
  {
    executor.scheduleAtFixedRate(new ScheduledThreadPoolExecutorTest().new MyTask(), 0, 5, TimeUnit.SECONDS);
  }
}
公共类ScheduledThreadPoolExecutorTest
{
public static ScheduledThreadPoolExecutor executor=new ScheduledThreadPoolExecutor(15);//没有多个实例,只有一个实例为所有请求提供服务
类MyTask实现Runnable
{
私人int最大尝试次数=10;
公开募捐
{

如果(++尝试运行此测试,它将打印
1 2 3 4 5
并停止

public class ScheduledThreadPoolExecutorTest {
    static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(15); // no
    static ScheduledFuture<?> t;

    static class MyTask implements Runnable {
        private int attempt = 1;

        public void run() {
            System.out.print(attempt + " ");
            if (++attempt > 5) {
                t.cancel(false);
            }
        }
    }

    public static void main(String[] args) {
        t = executor.scheduleAtFixedRate(new MyTask(), 0, 1, TimeUnit.SECONDS);
    }
}
公共类ScheduledThreadPoolExecutorTest{
静态ScheduledThreadPoolExecutor executor=新ScheduledThreadPoolExecutor(15);//否
静态调度未来t;
静态类MyTask实现Runnable{
私有int尝试=1;
公开募捐{
系统输出打印(尝试+“”);
如果(++尝试>5){
t、 取消(假);
}
}
}
公共静态void main(字符串[]args){
t=executor.scheduleAtFixedRate(newMyTask(),0,1,TimeUnit.SECONDS);
}
}

在线程外很好地取消:

public class ScheduleTest {

    @Test
    public void testCancel() throws Exception {
        final ScheduledThreadPoolExecutor EXECUTOR = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(2);
        ScheduledFuture f1 = EXECUTOR.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("Im alive 1");
            }
        }, 0, 1, TimeUnit.SECONDS);
        ScheduledFuture f2 = EXECUTOR.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("Im alive 2");
            }
        }, 0, 2, TimeUnit.SECONDS);

        Thread.sleep(10000);
        f1.cancel(true);
        System.out.println("f1 cancel");
        Thread.sleep(10000);
        f2.cancel(false);
        System.out.println("f2 cancel");
        Thread.sleep(10000);
    }
}

有时线程不能被取消,这通常通过
volatile boolean isCancelled解决;
CountDownLatch
是另一种方法。当线程完成时,在闩锁上调用
countDown()
。调用线程调用
闩锁。wait()
直到所有线程完成。此时调用
ExecutorService.shutdownNow()
,以便主线程不会变成僵尸

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExecutorTest {

  static int i = 0;

  public static void main(String[] args) throws Exception {
    final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
    final CountDownLatch latch = new CountDownLatch(1);
    executor.scheduleAtFixedRate(() -> {
        System.out.println(++i);
        if (i > 4) {
          latch.countDown();
        }
    }, 0, 100, TimeUnit.MILLISECONDS);
    latch.await();
    executor.shutdownNow();
  }
}

非常感谢!我确实知道scheduledfuture,但我尝试使用这种方式:t=executor.scheduleAtFixedRate(newmytask(),0,1,TimeUnit.SECONDS);t.cancel(true);由于明显的原因,这永远不会起作用。在任务实现中取消任务似乎是正确的。谢谢。这很有帮助。有趣的是,这个示例从不存在。我认为您需要执行器关闭,或者更确切地说,您需要一个
t.get()
和CancellationException的catch块中的执行器关闭这种方法是线程安全的吗?任务执行可能会在分配到主线程之前到达t.cancel(),从而导致NullPointerException。这是一个很好的示例,因为它会面临很多问题……谢谢:)