java - Spring控制器如何每次只服务一个请求,并丢弃同一方法收到的其他请求,直到第一个请求完成
问题描述
因此,正如标题所描述的,我想实现以下目标
@Controller
public class ImportController {
@RequestMapping(value = "/{File}", method = RequestMethod.GET)
@LogAware
public String import(@PathVariable(value = "File") String excel, Model model) {
try {
synchronized (this) {
//code...
}
}
}
}
我希望代码只针对一次出现的 1 个请求执行。同步块内的代码执行可持续约 1 小时。同时,我希望取消到达该方法的每个其他请求。有没有办法做到这一点?
只是为了澄清:
就像现在一样,第一个请求将被处理,当它完成时,等待锁的下一个请求将被处理,然后是下一个正在等待的请求。
我想要的是不允许在第一个请求完成后已经等待服务的其他请求。如果请求是在执行第一个请求期间出现的,我想向用户返回错误请求或其他内容并取消他们的请求。
解决方案
方法一:
使用单个许可信号量
这是一个示例代码:
import java.util.concurrent.Semaphore;
public class Test {
Semaphore s = new Semaphore(1); // Single permit.
public void nonBlockingMethod() throws InterruptedException {
// A thread tries to acquire a permit, returns immediately if cannot
if (s.tryAcquire()) {
// No. of permits = 0
try {
System.out.println(Thread.currentThread().getName() + " begins execution..");
// long running task
Thread.sleep(4000);
System.out.println(Thread.currentThread().getName() + " exiting..");
} finally {
s.release(); // Release permit. No. of permits = 1
}
} else {
System.out.println(Thread.currentThread().getName() + " cannot run as another thread is already running..");
}
}
}
方法二:
使用可重入锁
示例代码:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test {
Lock s = new ReentrantLock();
public void nonBlockingMethod() throws InterruptedException {
if (s.tryLock()) {
try {
System.out.println(Thread.currentThread().getName() + " begins execution..");
// long running task
Thread.sleep(4000);
System.out.println(Thread.currentThread().getName() + " exiting..");
} finally {
s.unlock();
}
} else {
System.out.println(Thread.currentThread().getName() + " cannot run as another thread is already running..");
}
}
}
司机:
public static void main(String[] args) throws InterruptedException {
Test t = new Test();
Runnable r = () -> {
try {
t.nonBlockingMethod();
} catch (InterruptedException e) {
e.printStackTrace();
}
};
for (int i = 0; i < 3; i++) {
new Thread(r, "Loop-1-Thread-" + i).start();
}
Thread.sleep(3999);
// one of the threads in this iteration may get to run the task
for (int i = 3; i < 8; i++) {
new Thread(r, "Loop-2-Thread-" + i).start();
}
}
(其中之一 )输出 :
Loop-1-Thread-2 cannot run as another thread is already running..
Loop-1-Thread-1 cannot run as another thread is already running..
Loop-1-Thread-0 begins execution..
Loop-2-Thread-3 cannot run as another thread is already running..
Loop-2-Thread-4 cannot run as another thread is already running..
Loop-2-Thread-5 cannot run as another thread is already running..
Loop-1-Thread-0 exiting..
Loop-2-Thread-6 begins execution..
Loop-2-Thread-7 cannot run as another thread is already running..
Loop-2-Thread-6 exiting..
推荐阅读
- excel - 64 位声明,PrtSafe?
- ios - iOS/Swift Core 数据合并冲突
- database - 为我的 NoSql 数据库模式建模时的注意事项
- python - 有没有更有效的方法在 Dataframe 中的每一行上带来特定值的总 .count() 值?(不合并,最好使用 lambda)
- javascript - 如何通过 jQuery 获取新的附加元素?
- javascript - 如何在 vue 项目中预加载图片
- c - C:MacLaurin 系列的自动错误检测并与内置的 sinx() 进行比较
- python - 从匀称导入几何 - 找不到指定的模块
- sql - 使用来自其他列的值创建一个非空列
- vxworks - 在 vxworks 中打印应用程序崩溃的堆栈跟踪