繁体   English   中英

如何正确停止 TimerTask

[英]How to correctly stop the TimerTask

所以基本上我有一个延迟任务会杀死一个 VPN pod。 我不想在不需要时拥有正在运行的 pod。

Desired 行为是当服务接收到请求(REST)时,它会取消现有任务并创建一个新任务,但会进一步延迟。

在我的解决方案中,我使用thread.stop()来取消已弃用一段时间的任务。

...

var VPN_TIMER_THREAD_NAME = "vpn-timer";
for (var thread : Thread.getAllStackTraces().keySet()) {
    if (thread.getName().equals(VPN_TIMER_THREAD_NAME)) {
        // Interrupted doesn't work for me
        thread.stop();
    }
}

var timer = new Timer(VPN_TIMER_THREAD_NAME);
timer.schedule(new TimerTask() {
            @Override
            public void run() {
              // New Transaction for EM
              TransactionStatus tx = VpnServiceImpl.this.txManager.getTransaction(new DefaultTransactionDefinition());
              try {
                var vpnToUpdate = VpnServiceImpl.this.em.find(Vpn.class, vpn.getId());
                doTearDown(vpnToUpdate);
                VpnServiceImpl.this.txManager.commit(tx);
              } catch (RuntimeException e) {
                log.error("Tear Down Error {}.", e.getMessage());
                VpnServiceImpl.this.txManager.rollback(tx);
              }
            }
          }, this.vpnProperties.delay());
...

private VpnStatusS2SDto doTearDown(Vpn vpn) {
    log.debug("In the tear down");
    this.client
        .pods()
        .inNamespace(this.kubeProps.getNamespace())
        .withLabel("app", "vpn-gateway")
        .withLabel("app.kubernetes.io/component", "vpn")
        .delete();

    entity.setModifiedDate(Instant.now());
    this.em.persist(entity);
    return mapper.toVpnStatusDto(entity);
}

当我更改为 thread.interrupt() 时,如果我提出多个请求,doTearDown 方法将多次调用。 使用 thread.stop 它“杀死”前一个任务并创建一个新任务,实际上拆解只被调用了一次。

我正在使用 Spring 引导。

有没有办法实现这种行为? 提前致谢

根据ewramner的回答,我找到了解决方案。 它按预期工作。 每个新请求都会取消现有任务并创建一个新任务。

我创建了嵌套任务 class:

private class ShutDownTask extends TimerTask {

    private final Vpn vpn;
    private final PlatformTransactionManager txManager;
    private final EntityManager em;

    ShutDownTask(Vpn vpn, PlatformTransactionManager txManager, EntityManager em) {
      this.vpn = vpn;
      this.txManager = txManager;
      this.em = em;
    }

    @Override
    public void run() {
        TransactionStatus tx = this.txManager.getTransaction(new 
        DefaultTransactionDefinition());
        try {
            var vpnToUpdate = this.em.find(Vpn.class, this.vpn.getId());
            doTearDown(vpnToUpdate);
            this.txManager.commit(tx);
        } catch (RuntimeException e) {
            this.txManager.rollback(tx);
        }
    }
}

在我的服务 class 中:

@Service
public class VpnServiceImpl {
    ...
    private final PlatformTransactionManager txManager;
    private final EntityManager em;
    private ShutDownTask shutDownTask;
    ...

    if (this.shutDownTask != null) {
      this.shutDownTask.cancel();
    }

    var timer = new Timer("vpn-timer");
    this.shutDownTask = new ShutDownTask(vpn, this.txManager, this.em);

    timer.schedule(this.shutDownTask, this.vpnProperties.delay());

    ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM