Vaadin 14 - 如何确保在 SessionDestroy 之后清除与会话相关的对象 [英] Vaadin 14 - How to make sure of session related objects get cleaned up after SessionDestroy

查看:40
本文介绍了Vaadin 14 - 如何确保在 SessionDestroy 之后清除与会话相关的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我在 Vaadin 14.1.18 SpringBoot 应用程序中的 MainView 类.

Here is my MainView Class in a Vaadin 14.1.18 SpringBoot application.

@Route
public class MainView extends VerticalLayout implements SessionDestroyListener{
    Logger logger = LoggerFactory.getLogger(MainView.class);

    public MainView() {
        // To make sure of doing some Houskeeping after Session Timeout
        VaadinService.getCurrent().addSessionDestroyListener(this);

        String sessionId = VaadinSession.getCurrent().getSession().getId();
        Zombie zombie = new Zombie(sessionId);
        zombie.start();

        add(new Span("Hey There! I'm at your disposal!!"));
    }

    @Override
    public void sessionDestroy(SessionDestroyEvent sessionDestroyEvent) {
        logger.warn("Just received a SessionDestroy Event with SessionId :: [{}]", sessionDestroyEvent.getSession().getSession().getId());
        // Performing the HouseKeeping stuff
    }
}

我还实现了一个僵尸进程,如下所示,我在 MainView 类中实例化了该进程.

I've also implemented a Zombie process as following which I had instantiated in my MainView Class.

public class Zombie extends Thread {
    Logger logger = LoggerFactory.getLogger(Zombie.class);
    private String sessionId;

    public Zombie(String sessionId) {
        this.sessionId = sessionId;
    }

    public void run() {
        while (true) {
            try {
                Thread.sleep(60000);
                Calendar cal1 = Calendar.getInstance();
                logger.info("Session [{}] :: Hey, I'm still alive at {}", sessionId, cal1.getTime());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

问题是,当相应的会话被销毁时,为什么附加到它的对象仍然存在?以下日志显示,即使在 SessionDestroy 之后,僵尸进程仍在运行.我是否必须采取一些特定措施来明确清理这些对象,或者 Vaadin 应该以某种方式自动处理它?<​​/p>

The question is, When the respective session gets destroyed, why the objects attached to it remain? the following log shows that, even after SessionDestroy, the zombie process is still running. Do I have to take some specific measures to explicitly clean these objects or Vaadin should handle it automatically somehow?

2020-03-07 02:32:02.891  INFO 6336 --- com.mypackage.Zombie : Session [B2CBB897208717EAE264C739E2D565BE] :: Hey, I'm still alive at Sat Mar 07 02:32:02 IRST 2020  
2020-03-07 02:32:56.580  WARN 6336 --- com.mypackage.MainView : Just received a SessionDestroy Event with SessionId :: [B2CBB897208717EAE264C739E2D565BE]  
2020-03-07 02:33:02.891  INFO 6336 --- com.mypackage.Zombie : Session [B2CBB897208717EAE264C739E2D565BE] :: Hey, I'm still alive at Sat Mar 07 02:33:02 IRST 2020  
2020-03-07 02:34:02.892  INFO 6336 --- com.mypackage.Zombie : Session [B2CBB897208717EAE264C739E2D565BE] :: Hey, I'm still alive at Sat Mar 07 02:34:02 IRST 2020

推荐答案

您在另一个问题中提到了垃圾收集.大多数情况下,会话销毁后,会被垃圾回收.

You mentioned garbage collection in another question. In most cases, after a session is destroyed, it will be garbage collected.

当 Java GC 运行时,它可能会垃圾收集所有不能通过垃圾收集根访问的东西.线程是根的一种类型,只要它们在运行,就永远不会被垃圾回收.

When the Java GC runs, it may garbage collect everything that is not accessible through a garbage collection root. Threads are one type of root, and are never garbage collected as long as they are running.

Vaadin 不知道您使用线程的意图是什么,也不知道如何安全地阻止它们.因此,您有责任阻止它们.

Vaadin can not know what your intentions with threads are, nor how to stop them safely. As such, it is your responsibility to stop them.

通常有两种方法可以停止线程,使用 interrupt() 或使用您自己的标志.

There are generally two ways to stop a thread, using interrupt() or with your own flag.

您应该使用哪一种取决于您的用例.如果您的线程正在休眠或以其他方式等待,中断将立即中断它(顾名思义)并抛出 InterruptedException.

Which one you should use depends on your use case. If your thread is sleeping, or otherwise waiting, an interrupt will interrupt it immediately (as the name implies) and an InterruptedException will be thrown.

如果您采用这种方法,请将您的 while(true) 更改为 while(!Thread.interrupted()),然后只需调用 zombie.interrupt() 停止它.如果线程当前正在休眠,则将到达您的 catch 块,因此如果它是正常行为,您可能不需要记录异常.

If you go with this approach, change your while(true) to while(!Thread.interrupted()), and simply call zombie.interrupt() to stop it. If the thread is currently sleeping, your catch block will be reached, so you might not need to log the exception if it's normal behavior.

注意:Thread.interrupted() 会在调用后重置中断标志,因此您不应例如在 catch 块中调用它.如果您想在不重置状态的情况下读取状态,可以使用 isInterrupted().

Note: Thread.interrupted() resets the interrupted flag after it's called, so you shouldn't, for example, call it in the catch block. You can use isInterrupted() if you want to read the state without resetting it.

另一种选择是使用您自己的标志.最简单的方法是添加一个 private volatile boolean stopped = false,并将你的 while (true) 更改为 while(!stopped).

The other option is to use your own flag. The simplest approach is to add a private volatile boolean stopped = false, and change your while (true) to while(!stopped).

volatile 关键字可确保值不会缓存在 CPU 中,这可能会延迟您的线程注意到值更改所需的时间.

The volatile keyword ensures the value is not cached in the CPU, which could delay the time it takes for your thread to notice the value change.

然后您可以添加一个方法来停止它,例如public void stop() { this.stopped = true;},并在会话销毁侦听器中调用它.由于这种方法不会中断正在等待的线程,因此它将始终完成循环的当前迭代,如果当前处于睡眠状态,则包括睡眠.

You can then add a method to stop it, e.g. public void stop() { this.stopped = true; }, and call that in the session destroy listener. As this approach does not interrupt a waiting thread, it will always finish the current iteration of the loop, including the sleep if it is currently sleeping.

这篇关于Vaadin 14 - 如何确保在 SessionDestroy 之后清除与会话相关的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆