请求线程是否在http请求之间重用?

时间:2012-08-30 02:34:13

标签: java multithreading google-app-engine thread-safety httprequest

我有一个带有true的java appengine应用程序。我知道多个线程将在处理多个并发请求的单个实例上运行。我知道代码必须是线程安全的,即没有全局静态变量。

我不明白的是,当请求结束时线程是否被杀死,或者一旦完成处理请求,是否可以使用相同的线程来处理另一个传入请求。

为什么这很重要?一些细节:

我有一个带有线程局部变量的静态类:

public abstract class Foo {
    private static final ThreadLocal<Boolean> threadIsApiCall = new ThreadLocal<Boolean>();
    static {
         setIsApiCall(false);
    }
}

此变量存储此线程的当前请求是对我们的rest api的调用,还是来自我们自己的自定义客户端的调用。仅当匹配我们的api路径的过滤器运行时,才会设置此变量。我遇到的问题是,如果向我们的API发出请求,并且threadlocal变量设置为true,则在后续请求(不是api请求)上,threadlocal变量仍设置为true。由于静态初始化程序,您会怀疑它会被设置为false。唯一可以设置为true的方法仍然是初始化程序没有运行,这使我相信线程被重用。这是真的吗?

2 个答案:

答案 0 :(得分:3)

线程重用是servlet实现的实现细节。线程通常通过线程池重用。这通常可以通过servlet配置进行配置。不幸的是,GAE并非如此。

您可以通过记录Thread.currentThread().getName()来检查GAE是否回收线程。

由于可能的线程重用,在servlet中使用ThreadLocal总是一个坏主意。如果需要在请求范围中存储某些数据,请使用servletRequest.setAttribute(..)

答案 1 :(得分:0)

静态{...}只被调用一次(每个类加载器,当类首次加载到内存中时)。

您需要为每个线程设置theadlocal值:

public abstract class Foo {
    private static final ThreadLocal<Boolean> threadIsApiCall = new ThreadLocal<Boolean>();

    public static void yourFirstMethodInvokedByCustomClient() {
         threadIsApiCall.set(false);
    }

    public static void yourFirstMethodInvokedByRESTAPI() {
         threadIsApiCall.set(true);
    }

    public static void anotherLaterMethod() {
         boolean isAPI = threadIsAPICall.get();
         ...
    }
}