【Java】Java Controller 每次只能一个请求 多线程 ReentrantLock
程序员文章站
2022-04-30 12:48:10
...
1.概述
背景我有一个程序,controller中接收客户端请求,但是这个请求做的操作非常的重,而且做完一个如果再来请求必须拒绝。因为这是一个费时的操作。而且多次操作会报错。
@GetMapper()
public void do(){
// 判断是否还有在运行的线程
// 线程是否允许完毕,如果没有,那么直接返回
// 否则就创建一个新的线程,然后立马返回,让线程在后台慢慢的跑
}
@GetMapper()
public void do2(){
// 判断是否还有在运行的线程
// 线程是否允许完毕,如果没有,那么直接返回
// 否则就创建一个新的线程,然后立马返回,让线程在后台慢慢的跑
}
上面两个方法只要有一个在运行,就不能创建新的线程
2.方案1
锁的方式实现
ExecutorService single = Executors.newSingleThreadExecutor();
private final ReentrantLock lock = new ReentrantLock();
/**
* 测试点:测试controoler中阻塞一个程序,每次只能一个程序过来
* @throws InterruptedException
* @throws ExecutionException
*/
@Test
public void test2() throws InterruptedException, ExecutionException {
redo1();
System.out.println("执行第一个");
System.out.println("执行第2个");
redo1();
Thread.sleep(Integer.MAX_VALUE);
}
private void redo1() {
if (lock.isLocked()) {
System.out.println("被锁在直接返回");
return;
}
lock.lock();
try {
System.out.println("进行提交");
feature = single.submit(new DeleteKafkaTopicRunable1(lock));
} catch (Exception e) {
System.out.println("执行释放锁111");
lock.unlock();
}
}
DeleteKafkaTopicRunable1 子线程
package com.java.thread.demo.pool.single;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author: chuanchuan.lcc
* @date: 2020-11-04 19:23
* @modifiedBy: chuanchuan.lcc
* @version: 1.0
* @description:
*/
public class DeleteKafkaTopicRunable1 implements Runnable {
private ReentrantLock lock = null;
public DeleteKafkaTopicRunable1(ReentrantLock lock) {
this.lock = lock;
}
@Override
public void run() {
System.out.println("线程开始运行"+Thread.currentThread().getName());
try {
Thread.sleep(3000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程运行结束"+Thread.currentThread().getName());
System.out.println(lock.isLocked());
System.out.println("开始释放锁");
// 这里是最坑爹的,这里居然不能释放锁
lock.unlock();
System.out.println("释放锁1");
}
}
里是最坑爹的,这里居然不能释放锁。导致程序只能进入一次。
3.方案2 Callable
@Test
public void test4() throws InterruptedException, ExecutionException {
redo();
System.out.println("执行第一个");
System.out.println("执行第2个");
redo();
Thread.sleep(Integer.MAX_VALUE);
}
private void redo() throws ExecutionException, InterruptedException {
if (feature != null) {
Boolean result = null;
Boolean result1 = null;
result1 = (Boolean) feature.isDone();
// result = (Boolean) feature.get(1000L, TimeUnit.SECONDS);
System.out.println(result);
System.out.println(result1);
if(result1){
lock.unlock();
}else {
System.out.println("被锁在直接返回");
return;
}
}
if (lock.isLocked()) {
System.out.println("被锁在直接返回");
return;
}
lock.lock();
try {
System.out.println("进行提交");
feature = single.submit(new DeleteKafkaTopicRunable());
} catch (Exception e) {
System.out.println("执行释放锁111");
lock.unlock();
}
Thread.sleep(2000L);
}
DeleteKafkaTopicRunable 方法
package com.java.thread.demo.pool.single;
import java.util.concurrent.Callable;
/**
* @author: chuanchuan.lcc
* @date: 2020-11-04 17:23
* @modifiedBy: chuanchuan.lcc
* @version: 1.0
* @description:
*/
public class DeleteKafkaTopicRunable implements Callable<Boolean> {
@Override
public Boolean call() throws Exception {
System.out.println("线程开始运行"+Thread.currentThread().getName());
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程开始运行结束"+Thread.currentThread().getName());
return false;
}
}
这样做更简单了,更容易实现了。
4. 多线程拒绝策略
上一篇: 万圣节恐怖装扮图片,恶搞自己,吓唬别人。
下一篇: PHP 过滤特殊字符和HTML字符对照表