欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-04-30 12:48:10
...

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

相关标签: 特殊