Java 如何阻止和取消阻止servlet线程?

Java 如何阻止和取消阻止servlet线程?,java,spring,multithreading,servlets,Java,Spring,Multithreading,Servlets,我有一个spring@RestController,因此是一个简单的servlet 如果servlet是用相同的值并发调用的(在本例中命名为“hash”),我想阻止除第一个servlet之外的所有servlet。当这一个完成时,我想释放被阻止的那个 作为解决方案,我考虑将散列添加到ConcurrentHashMap,并将servlet线程作为散列键的值添加到该散列映射中 但是我如何在那里添加一个运行的java线程呢 以下伪代码说明了我试图实现的目标: @RestController public

我有一个spring
@RestController
,因此是一个简单的
servlet

如果servlet是用相同的值并发调用的(在本例中命名为“hash”),我想阻止除第一个servlet之外的所有servlet。当这一个完成时,我想释放被阻止的那个

作为解决方案,我考虑将散列添加到
ConcurrentHashMap
,并将servlet线程作为散列键的值添加到该散列映射中

但是我如何在那里添加一个运行的java线程呢

以下伪代码说明了我试图实现的目标:

@RestController
public class MyService {
    //a map blocking any concurrent process on the same hash value
    private ConcurrentHashMap<String, List<Object>> map;

    @RequestMethod
    public String myXmlMethod(Param params) {
        String hash = params.getHash(); ////assume a value identifying a certain form of logic

        if (!map.contains(hash)) {
            //here no concurrent task is running, so block the hash until removal
            map.put(hash, new ArrayList<Object>());
            callLongRunningTaskAndWriteToDB();

            List<Object> threads = map.get(hash);
            map.remove(hash); //free the hash

            //interrupt any waiting threads, as the hash completed now
            if (threads != null && !threads.isEmpty()) {
                for (thread : threads) {
                    thread.interruptWait();
                }
            }
        } else {
            //this way the servlet thread cannot continue until the timout occurs,
            //or the servlet thread is canceled by the main thread in the concurrent hashmap
            thread = new Thread(this, Timeout.SECONDS(30));
            map.get(hash).add(thread);
            waitForThreadTimeoutOrInterrupt();
        }
    }
}
@RestController
公共类MyService{
//在同一哈希值上阻止任何并发进程的映射
私有ConcurrentHashMap;
@请求方法
公共字符串myXmlMethod(Param params){
String hash=params.getHash();///假设一个值标识某种形式的逻辑
如果(!map.contains(散列)){
//这里没有并发任务正在运行,因此请阻止哈希,直到删除为止
put(hash,newarraylist());
调用LongRunningTaskandWriteToDB();
List threads=map.get(散列);
map.remove(散列);//释放散列
//中断所有等待的线程,因为散列现在已完成
if(threads!=null&!threads.isEmpty()){
用于(线程:线程){
thread.interruptWait();
}
}
}否则{
//这样,servlet线程在超时发生之前无法继续,
//或者servlet线程被并发hashmap中的主线程取消
thread=新线程(这个,Timeout.SECONDS(30));
map.get(散列)、add(线程);
waitForThreadTimeoutOrInterrupt();
}
}
}

问题:但我如何才能真正获得该方法当前正在执行的“线程”的句柄?这样我就可以将它添加到映射中,然后等待并中断它?

如果您的问题只是如何获取当前线程,那么您可以使用类
thread
的静态方法获取当前线程

发件人:

返回对当前正在执行的线程对象的引用


如果您的问题只是如何获取当前线程,那么可以使用类
thread
的静态方法获取当前线程

发件人:

返回对当前正在执行的线程对象的引用


您可以作为
thread.currentThread
访问当前线程,如果这是您的问题,但是我看到您正在尝试为
调用LongRunningTaskandWriteToDB()
实现一种互斥,因此只有一个线程将执行该代码


使用基于Java的机制,比如
Java.util.concurrent.Semaphore
,不是更好吗?更重要的是,您可以在可运行任务中设置
callLongRunningTaskAndWriteToDB方法,并通过singleton访问该方法,确保只有一个线程执行该方法

您可以作为
thread.currentThread
访问当前线程,如果这是您的问题,但是我看到您正在尝试为
调用LongRunningTaskandWriteToDB()
实现一种互斥,因此只有一个线程将执行该代码


使用基于Java的机制,比如
Java.util.concurrent.Semaphore
,不是更好吗?更重要的是,您可以在可运行任务中设置
callLongRunningTaskAndWriteToDB方法,并通过singleton访问该方法,确保只有一个线程执行该方法

您可以使用
FutureTask
ConcurrentMap
来实现这一点,如下所示:

我们首先定义
ConcurrentMap

private final ConcurrentMap<String, FutureTask<MyResult>> map = new ConcurrentHashMap<>();
@RequestMethod
public String myXmlMethod(Param params) {
    String hash = params.getHash(); ////assume a value identifying a certain form of logic
    FutureTask<MyResult> task = new FutureTask<>(new Callable<MyResult>() {
        @Override
        public MyResult call() throws Exception {
            // My task here
        }
    });
    // This boolean means we are the first to insert the entry
    boolean inserted = true;
    try {
        FutureTask<MyResult> previous = map.putIfAbsent(hash, task);
        if (previous == null) {
            // The task has not been defined so far so we execute it
            task.run();
        } else {
            // the task has already been defined
            task = previous;
            inserted = false;
        }
        // we wait until we get the result
        return task.get();
    } finally {
        // Clean up the per key map but only if our insertion succeeded and with our future
        if (inserted) {
           map.remove(hash, task);
        }
    }
}
private final ConcurrentMap=new ConcurrentHashMap();
我们实现了防止两个线程同时执行相同任务的逻辑:

private final ConcurrentMap<String, FutureTask<MyResult>> map = new ConcurrentHashMap<>();
@RequestMethod
public String myXmlMethod(Param params) {
    String hash = params.getHash(); ////assume a value identifying a certain form of logic
    FutureTask<MyResult> task = new FutureTask<>(new Callable<MyResult>() {
        @Override
        public MyResult call() throws Exception {
            // My task here
        }
    });
    // This boolean means we are the first to insert the entry
    boolean inserted = true;
    try {
        FutureTask<MyResult> previous = map.putIfAbsent(hash, task);
        if (previous == null) {
            // The task has not been defined so far so we execute it
            task.run();
        } else {
            // the task has already been defined
            task = previous;
            inserted = false;
        }
        // we wait until we get the result
        return task.get();
    } finally {
        // Clean up the per key map but only if our insertion succeeded and with our future
        if (inserted) {
           map.remove(hash, task);
        }
    }
}
@RequestMethod
公共字符串myXmlMethod(Param params){
String hash=params.getHash();///假设一个值标识某种形式的逻辑
FutureTask task=新的FutureTask(新的可调用(){
@凌驾
公共MyResult调用()引发异常{
//我的任务在这里
}
});
//这个布尔值表示我们是第一个插入条目的
布尔插入=真;
试一试{
FutureTask previous=map.putIfAbsent(散列,任务);
如果(上一个==null){
//到目前为止,任务尚未定义,因此我们执行它
task.run();
}否则{
//任务已定义
任务=以前的任务;
插入=假;
}
//我们等到结果出来
return task.get();
}最后{
//清理每个键的映射,但前提是我们的插入成功,并且与我们的未来一致
如果(插入){
map.remove(散列,任务);
}
}
}

您可以使用
FutureTask
ConcurrentMap
实现这一点,如下所示:

我们首先定义
ConcurrentMap

private final ConcurrentMap<String, FutureTask<MyResult>> map = new ConcurrentHashMap<>();
@RequestMethod
public String myXmlMethod(Param params) {
    String hash = params.getHash(); ////assume a value identifying a certain form of logic
    FutureTask<MyResult> task = new FutureTask<>(new Callable<MyResult>() {
        @Override
        public MyResult call() throws Exception {
            // My task here
        }
    });
    // This boolean means we are the first to insert the entry
    boolean inserted = true;
    try {
        FutureTask<MyResult> previous = map.putIfAbsent(hash, task);
        if (previous == null) {
            // The task has not been defined so far so we execute it
            task.run();
        } else {
            // the task has already been defined
            task = previous;
            inserted = false;
        }
        // we wait until we get the result
        return task.get();
    } finally {
        // Clean up the per key map but only if our insertion succeeded and with our future
        if (inserted) {
           map.remove(hash, task);
        }
    }
}
private final ConcurrentMap=new ConcurrentHashMap();
我们实现了防止两个线程同时执行相同任务的逻辑:

private final ConcurrentMap<String, FutureTask<MyResult>> map = new ConcurrentHashMap<>();
@RequestMethod
public String myXmlMethod(Param params) {
    String hash = params.getHash(); ////assume a value identifying a certain form of logic
    FutureTask<MyResult> task = new FutureTask<>(new Callable<MyResult>() {
        @Override
        public MyResult call() throws Exception {
            // My task here
        }
    });
    // This boolean means we are the first to insert the entry
    boolean inserted = true;
    try {
        FutureTask<MyResult> previous = map.putIfAbsent(hash, task);
        if (previous == null) {
            // The task has not been defined so far so we execute it
            task.run();
        } else {
            // the task has already been defined
            task = previous;
            inserted = false;
        }
        // we wait until we get the result
        return task.get();
    } finally {
        // Clean up the per key map but only if our insertion succeeded and with our future
        if (inserted) {
           map.remove(hash, task);
        }
    }
}
@RequestMethod
公共字符串myXmlMethod(Param params){
String hash=params.getHash();///假设一个值标识某种形式的逻辑
FutureTask task=新的FutureTask(新的可调用(){
@凌驾
公共MyResult调用()引发异常{
//我的任务在这里
}
});
//这个布尔值表示我们是第一个插入条目的
布尔插入=真;
试一试{
FutureTask previous=map.putIfAbsent(散列,任务);
如果(上一个==null){
//到目前为止,任务尚未定义,因此我们执行它
task.run();
}否则{