我对 hibernate 还比较陌生,所以请保持温柔。我在长时间运行的方法(约 2 分钟长)和更改存储在数据库中的对象上的状态字段的值时遇到问题。下面的伪代码应该有助于解释我的问题。
public foo(thing) {
if (thing.getStatus() == "ready") {
thing.setStatus("finished");
doSomethingAndTakeALongTime();
} else {
// Thing already has a status of finished. Send the user back a message.
}
}
伪代码不需要太多解释。我希望 doSomethingAndTakeALongTime() 运行,但前提是它的状态为“就绪”。每当 doSomethingAndTakeALongTime() 完成需要 2 分钟并且事物状态字段的更改在离开 foo() 之前不会持久保存到数据库时,就会出现我的问题。因此,另一个用户可以在这 2 分钟内发出请求,if 语句将计算为 true。
我已经尝试过手动更新字段并刷新 session ,但似乎不起作用。我不知道从这里该怎么做,非常感谢任何帮助。
PS:我的 hibernate session 由 spring 管理。
最佳答案
基本上,您需要让它在单独的线程
中运行,以使该方法立即返回。否则它确实会阻塞,直到长时间运行的任务完成。您可以将实体本身传递给线程,以便它可以自行更新状态。这是使用简单Thread
的基本启动示例。
public class Task extends Thread {
private Entity entity;
public Task(Entity entity) {
this.entity = entity;
}
public void run() {
entity.setStatus(Status.RUNNING);
// ...
// Long running task here.
// ...
entity.setStatus(Status.FINISHED);
}
}
和
public synchronized void foo(Entity entity) {
if (entity.getStatus() == Status.READY) {
new Task(entity).start();
} else {
// ...
}
}
状态
位于 enum 中您甚至可以使用 switch
语句来代替 if/else
。
switch (entity.getStatus()) {
case READY:
new Task(entity).start();
break;
case RUNNING:
// It is still running .. Have patience!
break;
case FINISHED:
// It is finished!
break;
}
为了对正在运行的线程进行更强大的控制,您可能需要考虑 ExecutorService
反而。由此,您可以控制最大线程数并指定超时。
关于java - 长时间运行的方法会导致竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2917156/