【Java】Java Controller 每次只能一个请求 多线程 ReentrantLock

在这里插入图片描述

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. 多线程拒绝策略

猜你喜欢

转载自blog.csdn.net/qq_21383435/article/details/109501618