Ваадин 14 - Как убедиться, что связанные с сеансом объекты очищаются после SessionDestroy - PullRequest
1 голос
/ 07 марта 2020

Вот мой класс MainView в приложении Vaadin 14.1.18 SpringBoot.

@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
    }
}

Я также реализовал процесс Zomb ie, как описано ниже, который я создал в своем классе MainView.

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 процесс zomb ie все еще выполняется. Нужно ли принимать какие-то конкретные c меры, чтобы явно очистить эти объекты, или Ваадин должен как-то автоматически это обрабатывать?

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

1 Ответ

2 голосов
/ 07 марта 2020

Вы упомянули сборку мусора в другом вопросе. В большинстве случаев после уничтожения сеанса он будет собирать мусор.

При запуске Java G C он может собирать все, что недоступно из сборки мусора root. Потоки относятся к одному типу root и никогда не собираются мусором, пока они работают.

Ваадин не может знать, каковы ваши намерения с потоками, и как их безопасно остановить. Таким образом, вы обязаны остановить их.

Как правило, существует два способа остановить поток, используя interrupt() или с вашим собственным флагом.

Какой из них вы должны использовать, зависит от ваш вариант использования. Если ваш поток спит или иным образом ожидает, прерывание немедленно прервет его (как следует из названия), и будет выдан InterruptedException.

Если вы go при таком подходе, измените свой while(true) на while(!Thread.interrupted()), и просто позвоните zombie.interrupt(), чтобы остановить его. Если поток в данный момент спит, ваш блок catch будет достигнут, поэтому вам, возможно, не потребуется регистрировать исключение, если оно работает нормально.

Примечание : Thread.interrupted() сбрасывает прерванный флаг после того, как он вызван, так что вы не должны, например, вызывать его в блоке catch. Вы можете использовать isInterrupted(), если хотите прочитать состояние без его сброса.

Другой вариант - использовать свой собственный флаг. Самый простой подход - добавить private volatile boolean stopped = false и изменить while (true) на while(!stopped).

Ключевое слово volatile гарантирует, что значение не будет кэшировано в ЦП, что может привести к задержке времени, которое требуется чтобы ваш поток заметил изменение значения.

Затем вы можете добавить метод, чтобы остановить его, например, public void stop() { this.stopped = true; }, и вызвать его в слушателе уничтожения сеанса. Поскольку этот подход не прерывает ожидающий поток, он всегда заканчивает sh текущую итерацию l oop, включая режим сна, если он в данный момент спит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...