【发布时间】:2021-03-19 08:53:44
【问题描述】:
面对这样一个事实:当数据库不可用时,队列会因为任务停止运行而增长。为方法 run() 中执行的任务设置超时的最佳方法是什么?可能有一些使用 ExecutorService 的好方法?
@Service
public class AsyncWriter implements Writer, Runnable {
private LinkedBlockingQueue<Entry> queue = new LinkedBlockingQueue<>();
private volatile boolean terminate = false;
private AtomicInteger completedCounter = new AtomicInteger();
@PostConstruct
private void runAsyncWriter() {
Thread async = new Thread(this);
async.setName("Writer Thread");
async.setPriority(2);
async.start();
}
@Override
public void run() {
while (!terminate) {
try {
Entry entry = queue.take();
dao.save(entry);
completedCounter.incrementAndGet();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void write(Entry entry) {
queue.add(entry);
}
}
【问题讨论】:
-
要么自己不运行任务,而是使用
TaskScheduler,或者有一个标志来计算run()中遇到的错误,如果错误超过阈值,你可以使用Thread.sleep()声明 -
此外,您还需要另一个
catch语句来捕获数据库不可用时引发的错误,否则您的run()将在第一个异常后终止 -
问题:为什么需要异步保存
Entrys 到数据库?这个构造是仅用于当数据库不可用的情况,还是您有特定的用例 -
因为这是后台,低优先级任务。这个结构总是被使用,它必须在数据库不可用时跳过一些超时的任务。
-
但主要原因是BlockingQueue如果不异步运行会阻塞整个应用程序。