ScheduledFuture отмены (true) с продувкой все еще выполняется - PullRequest
0 голосов
/ 15 мая 2018

Мне кажется, что я прочитал почти каждый пост на SO о ScheduledThreadPoolExecutor и ScheduledFutures и их отмене.

По сути, у меня есть ScheduledThreadPoolExecutor с 30 потоками в пуле.Я планирую задачи, используя #schedule (Runnable, delay, TimeUnit) как способ обработки таймаутов.Runnable занимает очень маленькую площадь (заполняет POJO значениями, преобразует в JSON и отправляет в конечную точку REST, которую я настроил на сервере в закрытой сети).

public class MyObject {
  private String name;
  private ScheduledFuture<Void> future;

  public MyObject(String name) {
    this.name = name;
  }

  public String getName() {
    return this.name;
  }

  public ScheduledFuture<Void> getFuture() {
    return future;
  }

  public void setFuture(ScheduledFuture<Void> future) {
    this.future = future;
  }
}

public class TimeoutTask implements Runnable {
  @Override
  public void run() {
    // Build POST HTTP object

    // Send to server, receive response

    // No, I'm not catching any exceptions here (might be the issue)
  }
}

public class Util {
  private static final ScheduledThreadPoolExecutor SCHEDULER = new ScheduledThreadPoolExecutor(30);
  private static final HashMap<String, MyObject> OBJECTS = new HashMap<>();

  static {
    // Eject tasks from the queue upon cancellation
    SCHEDULER.setRemoveOnCancelPolicy(true);
    MyObject object1 = new MyObject("test");
    OBJECTS.put(object1.getName(), object1);

    MyObject object2 = new MyObject("test2");
    OBJECTS.put(object2.getName(), object2);

    MyObject object3 = new MyObject("test3");
    OBJECTS.put(object3.getName(), object3);
  }

  public static ScheduledFuture<Void> scheduleTask(int timeoutInSeconds){
    return SCHEDULER.schedule(new TimeoutTask(), timeoutInSeconds, TimeUnit.SECONDS);
  }

  public static void cancelTask(String name) {
    MyObject object = getObject(name);
    if (object != null){
      object.getFuture().cancel(true);
    }
  }

  public static MyObject getObject(String name) {
    return OBJECTS.get(name);
  }
}

@Controller
public class Controller {

  // REST BOILERPLATE
  @RequestMapping(...)
  public void receive(Message message) {
      if (message.getType().equals(MessageType.CANCEL)) {
          Util.cancelTask(message.getObjectName());
      }
  }
}

@Component
public class View {

  @PostConstruct
  public void init() {
    JFrame frame = new JFrame();
    JPanel panel = new JPanel();
    JButton button = new JButton("Do Something");
    button.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        Util.getObject("test").setFuture(Util.scheduleTask(5));
        Util.getObject("test1").setFuture(Util.scheduleTask(15));
        Util.getObject("test2").setFuture(Util.scheduleTask(60));
      }
    });
    panel.add(button);
    frame.add(panel);
    frame.pack
    frame.setVisible(true);
  }
}

Я отменяю ScheduledFuture, используяЗначение true, чтобы разрешить прерывание выполнения, и я оценил очередь до и после, чтобы увидеть, будет ли она извлечена, и это так, но задача все еще выполняется после того, как задержка завершит .

Любая помощь здесь будет потрясающей.Этот пример очень сокращен, но я по крайней мере хотел показать, что я использую Spring, ссылаясь на тайм-ауты в общем классе Util (поэтому мои ссылки не перепутываются), и что это, очевидно, многопоточный шаблон MVC, гдеКонтроллер может получать множество сообщений и распределять несколько потоков для обработки этих сообщений, что может привести к отмене фьючерса, если тип сообщения правильный.

...