如果出现问题并且我想重试,使用相同的 Executor 重新排队 Runnable 是否安全或明智?
我刚刚在我的 runnable 的 run()
方法中编写了这段代码:
try {
dbConnection = MyApp.datasource.getConnection();
} catch (SQLException e) {
logger.log(Level.SEVERE, "Could not obtain a DB connection! Re-enqueuing this task. Message: " + e.getMessage(), e);
MyApp.executor.execute(this);
return;
}
如您所见,如果任务无法获得数据库连接,它应该将自己重新排队到它所在的同一队列中在它运行之前。
我认为这可能是安全的,但感觉很有趣,我只是想确保没有遗漏任何问题。
谢谢!
I just wrote this code in my runnable's run()
method:
try {
dbConnection = MyApp.datasource.getConnection();
} catch (SQLException e) {
logger.log(Level.SEVERE, "Could not obtain a DB connection! Re-enqueuing this task. Message: " + e.getMessage(), e);
MyApp.executor.execute(this);
return;
}
As you can see, if the task can't obtain a DB connection, it should re-enqueue itself, into the same queue it was in before it ran.
I'm thinking this is probably safe, but it feels funny, and I just want to make sure there aren't any gotchyas that I'm missing.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
就执行者而言,这很好。
但请记住,失败可能会很快发生,然后执行器可能会快速重新运行您的代码。这可能会导致大量 CPU 消耗而没有任何结果。
内置强制重试延迟和最大循环计数。
This is fine as far as the executor goes.
But keep in mind that failures may occur pretty quickly, and then the Executor may re-run your code quickly. This can result in burning a lot of CPU for no results.
Build in forced retry delays and maximum loop counts.
存在出现所谓的有毒消息的风险:如果
SQLException
无法消失,任务将无限重复。您必须提供某种计数器或计时器。根据执行器的占用情况(已经调度了多少个并发任务),重试之间的间隔可能会有很大差异。您可能会使用 100% 的 CPU,或者等待重试很长时间。
如果偶然,您的父任务(重新安排自身的任务)等待子(重新安排)调用的结果,您可能会当执行器仅在一个线程上运行时,会遇到死锁。
您正在使用
MyApp
的原始字段,无论如何似乎都是一个糟糕的模式。至于总体思路:为什么不在
run()
中有一个循环呢?您想对正在执行的其他任务更加“公平”吗?There is a risk of so called poison message to occur: the task will repeat itself infinitely if the
SQLException
won't get away. You must provide some sort of counter or timer.Depending on the occupancy of the executor (how many concurrent tasks are already scheduled), the interval between retries may vary significantly. You might either use 100% of the CPU or wait for retry for a very long time.
If, by incident, your parent task (the one that re-schedules itself) waits for the result of the child (re-scheduled) invocation, you might experience deadlock when the executor runs on only one thread.
You are using raw fields of
MyApp
, seems like a bad pattern whatsoever.As for the overall idea: why not just have a loop in
run()
? You want to be more "fair" to other tasks being executed?