ScheduledExecutorService withFixedDelay перестает работать через несколько дней

Написал телеграм бота, который парсит сайт и, спустя некоторое время, отправляет информацию в телеграм.

public class Bot extends TelegramLongPollingBot {

private Map<Long, Integer> usersSelection = new HashMap<Long, Integer>();

private static AtomicBoolean postStarted=new AtomicBoolean();

private static Bot bot;

private static Logger logger;

private static JdbcManager jdbcManager;

private static Timer postmanTimer;

public static void main(String[] args) {
    Configurer configurer = new Configurer();
    ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
    jdbcManager= (JdbcManager)context.getBean("jdbcManager");
    logger=new Logger(configurer);
    ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
    service.scheduleWithFixedDelay(new Aggregator(configurer, jdbcManager), 20, 20, TimeUnit.MINUTES);
    ApiContextInitializer.init();
    TelegramBotsApi telegramBotsApi = new TelegramBotsApi();
    try {
        bot=new Bot();
        telegramBotsApi.registerBot(bot);
    }catch (TelegramApiException e){
        logger.logs(e.getMessage());
        e.printStackTrace();
    }
}
@Override
public void onUpdateReceived(Update update) {
    if (update.hasMessage()){
        Message message = update.getMessage();
        if (message!=null&&message.hasText()) {
            MessageHandler messageHandler = new MessageHandler(bot, usersSelection, message, postStarted, jdbcManager);
            messageHandler.permitter();
        }
    }else if (update.hasCallbackQuery()){
        try {
            if (!postStarted.get()){
                postmanTimer=new Timer();
            }
            CallBacker callBacker=new CallBacker(bot,update.getCallbackQuery(),postStarted,
                    usersSelection,jdbcManager,postmanTimer);
            callBacker.caser();
        } catch (Exception e) {
            logger.logs(e.getMessage());
            e.printStackTrace();
        }
    }
}

@Override
public String getBotUsername() {
    return "bot_username";
}

@Override
public String getBotToken() {
    return "000000000:AAEASfagefewyur-dgrfqefqewfgqe";
}

}

За парсинг отвечает класс Aggregator, который я запускаю в отдельном потоке

public class Aggregator implements Runnable {

private Parser parser;

private Configurer configurer;

private Logger logger;

private JdbcManager jdbcManager;

public Aggregator(Configurer configurer, JdbcManager jdbcManager) {
    this.configurer = configurer;
    this.parser = new Parser();
    this.logger = new Logger(configurer);
    this.jdbcManager = jdbcManager;
}

@Override
public void run() {
    try {
        logger.logs("Start aggregator...");
        List<String> articleUrls = getArticleUrls();
        if (articleUrls != null && !CollectionUtils.isEmpty(articleUrls)) {
            for (String articleUrl : articleUrls) {
                try {
                    parser.parseArticleUrl(articleUrl,jdbcManager,configurer);
                } catch (Exception e) {
                    logger.logs("From aggregator run"+e.getMessage());
                }
            }
        }
    }catch (Throwable t){
        t.printStackTrace();
    }
}

private List<String> getArticleUrls() {
    List<String> articleUrls = new ArrayList<>();

    List<String> likeKeyWords = new ArrayList<>();
    try {
        likeKeyWords = jdbcManager.getLinesFromList(configurer.getLikeKeyWordsDir());
    } catch (Exception e) {
        logger.logs("from getArticleUrls "+e.getMessage());
    }
    for (String likeKeyWord : likeKeyWords) {
        try {
            List<String> urlsFromDzenParser = parser.getDzenArticleUrlsByKeyWord(likeKeyWord);
            if (!CollectionUtils.isEmpty(urlsFromDzenParser)) {
                jdbcManager.resetMissFromDzenParser();
                articleUrls.addAll(urlsFromDzenParser);
            } else {
                jdbcManager.missFromDzenParserIncrease();
            }
        } catch (Exception e) {
            jdbcManager.missFromDzenParserIncrease();
            logger.logs(e.getMessage() + "getDzenArticleUrlsByKeyWordMiss LIKEKEYWORD " + likeKeyWord);
        }
    }
    return articleUrls;
}

}

Всё работает нормально, но через 2-3 дня я обнаруживаю, что ScheduledExecutorService в какое-то время просто перестаёт запускать новый поток. Перезапускаю приложение- и снова 2-3 дня и новый поток не запускается. Я читал, что дело может быть в том, что поток выбрасывает исключения и новое выполнение потоков подавляется. Для этого я обернул метод run в try catch Throwable. Ситуацию это не спасло.

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

jstack

"pool-1-thread-1" #11 prio=5 os_prio=0 tid=0x00007f0390f8c800 nid=0x6133 runnable [0x00007f03271f4000]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:171)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:457)
    at sun.security.ssl.SSLSocketInputRecord.decodeInputRecord(SSLSocketInputRecord.java:237)
    at sun.security.ssl.SSLSocketInputRecord.decode(SSLSocketInputRecord.java:190)
    at sun.security.ssl.SSLTransport.decode(SSLTransport.java:108)
    at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1146)
    at sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1116)
    - locked <0x00000005e391a668> (a sun.security.ssl.SSLSocketImpl)
    at sun.security.ssl.SSLSocketImpl.access$200(SSLSocketImpl.java:72)
    at sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:815)
    - locked <0x00000005e391a6d8> (a sun.security.ssl.SSLSocketImpl$AppInputStream)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:284)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
    - locked <0x00000005e391a6f8> (a java.io.BufferedInputStream)
    at org.apache.commons.httpclient.WireLogInputStream.read(WireLogInputStream.java:69)
    at org.apache.commons.httpclient.ContentLengthInputStream.read(ContentLengthInputStream.java:170)
    at java.io.FilterInputStream.read(FilterInputStream.java:133)
    at org.apache.commons.httpclient.AutoCloseInputStream.read(AutoCloseInputStream.java:108)
    at java.io.FilterInputStream.read(FilterInputStream.java:107)
    at org.apache.commons.httpclient.AutoCloseInputStream.read(AutoCloseInputStream.java:127)
    at org.apache.commons.httpclient.HttpMethodBase.getResponseBody(HttpMethodBase.java:690)
    at org.apache.commons.httpclient.HttpMethodBase.getResponseBodyAsString(HttpMethodBase.java:803)
    at com.dzen.monitor.bot.core.Parser.getDzenArticleUrlsByKeyWord(Parser.java:180)
    at com.dzen.monitor.bot.scheduler.Aggregator.getArticleUrls(Aggregator.java:70)
    at com.dzen.monitor.bot.scheduler.Aggregator.run(Aggregator.java:33)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

Ответы (0 шт):