Гость
Форумы / Java [игнор отключен] [закрыт для гостей] / Корректное закрытие потоков. / 25 сообщений из 35, страница 1 из 2
24.07.2019, 19:27
    #39841108
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
Всем привет!
Задача такая: веб-приложение при старте должно запускать несколько процессов (заранее неизвестно сколько), которые должны шуршать в фоне.
Делаю на грубом примере так:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
package com.mycompany.testweb;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

public class DaemonClass implements Runnable{

    @Override
    public void run() {
        String filePath = "D:\\myfile.txt";
        String text = "Ку!\n";

        while (true) {
            try {
                Files.write(Paths.get(filePath), text.getBytes(), StandardOpenOption.APPEND);
            } catch (IOException e) {
                System.out.println(e);
            }

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(DaemonClass.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }    
}

package com.mycompany.testweb;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class IniClass implements ServletContextListener {
    private Thread thread;
    
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        DaemonClass daemonClass = new DaemonClass();
         thread = new Thread(daemonClass);
         thread.start();
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        thread.interrupt();
    }
    
}


Все работает.
Но потом делаем undeploy приложения, а файл все равно пишется.
Похоже, что при андеплое приложения не приходим в contextDestroyed.
Остановить можно только андеплой плюс рестарт веб-сервера.
Возникает вопрос как сделать, чтобы "дочерний" поток прерывался при дисейбле/андеплое приложения на сервере.
Переписываем в зародыш маленького ада:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
package com.mycompany.testweb;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class IniClass implements ServletContextListener, Runnable {
    private Thread mainThread;
    private Thread thread;
    private DaemonClass daemonClass = null;
    
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        mainThread = new Thread(this);
        mainThread.start();
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        daemonClass.setIsInterrupted(true);
        thread.interrupt();
    }

    @Override
    public void run() {
        daemonClass = new DaemonClass();
        thread = new Thread(daemonClass);
        thread.start();
    }
}


И каким-то чудом теперь все работает как требуется.
Но хотелось бы понять, в чем фишка?
Почему работает в данном случае как надо, только если лисенер сам себя засовывает в поток?
(как понял, только в этом случае приходим в contextDestroyed).
И возможно, как реализовать правильнее?
...
Рейтинг: 0 / 0
24.07.2019, 19:50
    #39841113
Basil A. Sidorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
"Веб-приложение" работает в сервлет-контейнер.
Жизненный цикл сервлета предусматривает методы init() и destroy().
Метод destroy() должен выставить флаг "кончай работу" и любым способом контролировать число оставшихся в работе потоков
Ваш(и) метод(ы) обязан(ы) регулярно проверять этот флаг, чтобы иметь возможность корректно завершаться без ударов киянкой по голове.
...
Рейтинг: 0 / 0
24.07.2019, 21:11
    #39841123
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
Basil A. Sidorov, это понятно. Но даже если вместо interrupt использовать флаг, который при выставлении в contextDestroyed выходит из цикла в методе run, поведение получается точно такое же (поток не останавливается при undeploy/disable).
Понятно, что по флагу правильнее "мягче", но вопрос в том почему второй вариант работает и мы приходим в contextDestroyed, а первый нет.
...
Рейтинг: 0 / 0
24.07.2019, 21:21
    #39841126
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
JDSкаким-то чудом теперь все работает как требуется.про чудо потом. Ты скажи что он пишет в файл, если старший ушел с сервера? Может это и правильно, не вырубать его? Посреди работы?
...
Рейтинг: 0 / 0
24.07.2019, 22:00
    #39841136
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
PetroNotC Sharp, пишет ровно то, что в коде "Ку!".
Вырубать его однозначно надо. По флагу или нет, вопрос не в этом.
...
Рейтинг: 0 / 0
24.07.2019, 22:32
    #39841144
asv79
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
JDSИ каким-то чудом теперь все работает как требуется.
Но хотелось бы понять, в чем фишка?
Почему работает в данном случае как надо, только если лисенер сам себя засовывает в поток?
(как понял, только в этом случае приходим в contextDestroyed).
И возможно, как реализовать правильнее?

дружище ты никогда не станешь программистом нормальным если будешь задавать такие вопросы
другими словами ты забиваешь свою голову тем,что тебе не нужно )
сделал - работает - расслабь булки и получай удовольствие
...
Рейтинг: 0 / 0
24.07.2019, 23:01
    #39841153
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
JDSВырубать его однозначно надов оракле вырубается набором kill.
Поэтому хороший поток кончить должен" (с)
...
Рейтинг: 0 / 0
25.07.2019, 07:57
    #39841196
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
asv79, главное не купить билет на самолет, автопилот к которому сам же написал по такому принципу
PetroNotC Sharp, про оракле не понял)
...
Рейтинг: 0 / 0
25.07.2019, 08:12
    #39841199
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
JDS,
В оракле и линуксе я кончаю поток набором kill в командной строке.
Почему у тебя поток работает без бензина ты не рассказал.
Может его изменить так чтобы он работал только под конкретную задачу, 1-10 сек.
Приложение выгрузил (а не выдернул из розетки) и поток доделал свою задачу.
Это вопрос чисто по постановке.
...
Рейтинг: 0 / 0
25.07.2019, 08:57
    #39841210
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
PetroNotC Sharp, в том и дело, что без бензина не надо работать (если это про ведущий поток). Да, можно завершить нормально без прерывания, но вопрос другой. Насчет кил операционкой "это же не наш метод" (с) )
...
Рейтинг: 0 / 0
25.07.2019, 09:42
    #39841227
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
JDSчто без бензина не надо работать (если это про ведущий поток).у тебя не ведущий и не основной. На основном томкат сидит.
Доп.поток создал ты сам. Почему он не заканчивает а крутится на бесконечном цикле?
...
Рейтинг: 0 / 0
25.07.2019, 09:45
    #39841229
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
JDS,
Пример.
Сброс кэша в лог файл.
Приложение закрыл, а в файл записывается и дескриптор закрывается.
Почему у тебя не так?
...
Рейтинг: 0 / 0
25.07.2019, 10:44
    #39841262
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
PetroNotC Sharp, это понятно что сам.
Например, он должен периодически проверять директорию на предмет появления там файлов, например, он должен держать коннект с другой прогой и тд. В общем этот поток должен работать пока работает основной (про основной томкат не будем, итак все время всторону уходим)).
...
Рейтинг: 0 / 0
25.07.2019, 11:24
    #39841286
qasta
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
JDS
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
        while (true) {
            try {
                Files.write(Paths.get(filePath), text.getBytes(), StandardOpenOption.APPEND);
            } catch (IOException e) {
                System.out.println(e);
            }

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException ex) {
                Logger.getLogger(DaemonClass.class.getName()).log(Level.SEVERE, null, ex);
                // вот тут надо было добавить выход из цикла (return или break)
            }
        }



И возможно, как реализовать правильнее?

У вас бесконечный цикл, который не заканчивается - добавил комментарий в то место, где ошибка.
Правильнее было бы написать не while (true) а while (workingFlag)
А в вызове contextDestroyed выставлять workingFlag = false и дожидаться через другой флаг того, что поток действительно завершился.

Пишу упрощенно - "через флаг", но в действительности есть много классов для многопоточной работы и правильнее было бы через них, но это уже надо делать "во второй серии".

Не забудьте на ваши "флаги" добавить ключевое слово volatile (ну или обрамить доступ к ним методами с synchronized)
...
Рейтинг: 0 / 0
25.07.2019, 11:33
    #39841294
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
Натянуты твои задачи.
Если они фоновые, то и делай отдельное приложение демон и старт, стоп.
Если нет, то нефиг молотить операционку на предмет - есть ли изменения при простом деплое.
ЛЮБОЙ СТАРТ ПРОГЕРА ДОЛЖЕН ИМЕТЬ СТОП В API.
Да и приложение может быть развернуто вообще в докере где нет файловой системы и d: и с:
JDS
Код: java
1.
String filePath = "D:\\myfile.txt";
...
Рейтинг: 0 / 0
25.07.2019, 11:34
    #39841298
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
qastaУ вас бесконечный циклда. Но он сопротивляется.
В его API не предусмотрено СТОП))
...
Рейтинг: 0 / 0
25.07.2019, 11:39
    #39841299
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
PetroNotC Sharp, ну елы-палы, ребят, я ж уже 4 раза сказал, что это просто пример и вопрос в другом
Про флаг это понятно.
Почему в первом случае не приходим в обработчик ondestroy, а во втором приходим)
Ну не задавал же я вопрос про флаг и натянутость задачи).
Да. Спросил, как сделать лучше, но в рамках примера (те поток шуршит все время пока жив породивший поток).
...
Рейтинг: 0 / 0
25.07.2019, 11:39
    #39841301
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
qastaА в вызове contextDestroyedу него не вызывается. В этом вопрос.
...
Рейтинг: 0 / 0
25.07.2019, 11:40
    #39841303
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
PetroNotC SharpqastaА в вызове contextDestroyedу него не вызывается. В этом вопрос.
Вызывается, но только во втором варианте.
Вопрос в том почему.
...
Рейтинг: 0 / 0
25.07.2019, 11:44
    #39841307
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
JDSPetroNotC Sharpпропущено...
у него не вызывается. В этом вопрос.
Вызывается, но только во втором варианте.
Вопрос в том почему.убери для вопроса все лишнее вместе с классом.
Вызывается?
И ссылку сюда на доки.
...
Рейтинг: 0 / 0
25.07.2019, 12:01
    #39841317
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
Наворотил кода по памяти, а пртом спрашивает почему не работает.
А обычно пишут - написал, протестил. Написал, протестил.
...
Рейтинг: 0 / 0
25.07.2019, 12:10
    #39841325
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
PetroNotC Sharp, два простых примера, отражающие суть вопроса и не по памяти, а вполне протестированы. Если бы наворотил, то притащил бы сюда весь код)
...
Рейтинг: 0 / 0
25.07.2019, 12:29
    #39841334
qasta
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
JDSPetroNotC Sharpпропущено...
у него не вызывается. В этом вопрос.
Вызывается, но только во втором варианте.
Вопрос в том почему.

В вашем верхнем примере цикл никогда не закончится - ему наплевать на какие-то там флажки и прочее.
Почему - я написал.

Именно для того, чтобы поток нельзя было прервать где и когда захочется (эквивалент kill -9) и убрали метод Thead.stop().
Для прерывания в "заранее оговоренных местах" используются "флаги". Я вам написал, что надо сделать.
Вы сделайте и протестируйте.
...
Рейтинг: 0 / 0
25.07.2019, 12:31
    #39841335
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
JDSотражающие суть вопросасуть ПРОГРАММИРОВАНИЯ в ПОСЛЕДОВАТЕЛЬНЫХ шагах.
У вас из первого кода не следует второй кусок.
Нужно первый кусок - рабочий и второй с ошибкой.
...
Рейтинг: 0 / 0
25.07.2019, 13:12
    #39841359
JDS
JDS
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Корректное закрытие потоков.
qasta, вот хотел же написать пример с флагом, тк понимал, что возможно народ пойдет в эту сторону, но понадеялся, что обьясню, а зря :)
Я же говорю, что и с флагом поведение ровно такое же, вопрос не в этом.

PetroNotC Sharp, второй вариант, который работает как надо был получен методом тыка, поэтому конечно второй кусок не следует из первого.
Различие в первом и втором примере очевидно, ну внутренняя суть не ясна: почему в 1 варианте не приходим в блок "финализации" сервлета.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Корректное закрытие потоков. / 25 сообщений из 35, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]