我想做什么?
当 2+ 个前端通过套接字发出请求某些内容时,我只希望后端处理其中 1 个请求并拒绝其他请求。
当前尝试执行此操作的代码是什么?
后端代码。
// Original code.
public IoMessage create(IoMessage request) {
Adventure[] adventures = null;
AdventureIoMessage createRequest = null;
StringBuilder message = new StringBuilder();
// Thinking of putting some "locking" code around this if statement?
// Something like "If this function is already in process, deny other requests and remove them"?
if (request instanceof AdventureIoMessage) {
createRequest = (AdventureIoMessage) request;
DatabaseManager databaseManager = Application.getDatabaseManager();
Adventure adventure = Adventure.read(databaseManager);
if (adventure == null || adventure.getStartTime() == 0 || !adventure.isActive()) {
createAdventure(adventures, createRequest, message);
} else {
message.append("New adventure already exists and hasn't ended yet!");
}
} else {
message.append("Request formatting is invalid!");
}
return new AdventureIoMessage(adventures, createRequest, message);
}
// My suggested code 1 using a Boolean.
public IoMessage create(IoMessage request) {
Adventure[] adventures = null;
AdventureIoMessage createRequest = null;
StringBuilder message = new StringBuilder();
Boolean isRequestAlreadyRunning = false;
if (!isRequestAlreadyRunning) {
isRequestAlreadyRunning = true;
if (request instanceof AdventureIoMessage) {
createRequest = (AdventureIoMessage) request;
DatabaseManager databaseManager = Application.getDatabaseManager();
Adventure adventure = Adventure.read(databaseManager);
if (adventure == null || !adventure.isActive()) {
createAdventure(adventures, createRequest, message);
} else {
message.append("New adventure already exists and hasn't ended yet!");
}
} else {
message.append("Request formatting is invalid!");
}
isRequestAlreadyRunning = false; // Done processing.
}
return new AdventureIoMessage(adventures, createRequest, message);
}
// My suggested code 2 using AtomicBoolean and CountDownLatch.
public IoMessage create(IoMessage request) {
Adventure[] adventures = null;
AdventureIoMessage createRequest = null;
StringBuilder message = new StringBuilder();
AtomicBoolean updateStarted = new AtomicBoolean();
CountDownLatch updateFinished = new CountDownLatch(1);
if (updateStarted.compareAndSet(false, true) {
if (request instanceof AdventureIoMessage) {
createRequest = (AdventureIoMessage) request;
DatabaseManager databaseManager = Application.getDatabaseManager();
Adventure adventure = Adventure.read(databaseManager);
if (adventure == null || !adventure.isActive()) {
createAdventure(adventures, createRequest, message);
} else {
message.append("New adventure already exists and hasn't ended yet!");
}
} else {
message.append("Request formatting is invalid!");
}
updateFinished.countDown();
} else {
updateFinished.await();
}
return new AdventureIoMessage(adventures, createRequest, message);
}
对于建议的代码 2,也尝试了AtomicBoolean
唯一的。
我期望结果是什么?
我考虑保留某种变量来检查是否create()
应该仍然发生,期望只有 1 个请求通过。
实际结果是什么?
当 2+ 个前端通过套接字发出请求某些东西时,create()
尽管内部有检查逻辑,但其中有 2 个会发生。
我认为问题可能是什么?
一个时间问题,因为 2+ 前端可以create()
在没有适当检查的情况下同时访问此方法。代码的原始逻辑在它们不会同时触发的过程中起作用。我希望这是有道理的,因为很难说这对 Java 来说是新事物。
编辑:
我最终确定的工作解决方案是:
// Within a class...
AtomicBoolean isRequestAlreadyRunning = new AtomicBoolean();
public IoMessage create(IoMessage request) {
Adventure[] adventures = null;
AdventureIoMessage createRequest = null;
StringBuilder message = new StringBuilder();
if (updateStarted.compareAndSet(false, true) {
try {
if (request instanceof AdventureIoMessage) {
createRequest = (AdventureIoMessage) request;
DatabaseManager databaseManager = Application.getDatabaseManager();
Adventure adventure = Adventure.read(databaseManager);
if (adventure == null || !adventure.isActive()) {
createAdventure(adventures, createRequest, message);
} else {
message.append("New adventure already exists and hasn't ended yet!");
}
} else {
message.append("Request formatting is invalid!");
}
} finally {
isRequestAlreadyRunning.set(false);
}
}
return new AdventureIoMessage(adventures, createRequest, message);
}