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)