2

我有一个 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 的唯一方法是,如果初始化程序没有运行,这让我相信线程被重用了。这是真的?

4

2 回答 2

3

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

您可以通过 logging 简单地检查 GAE 是否回收线程Thread.currentThread().getName()

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

于 2012-08-30T08:49:02.577 回答
0

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

您需要为每个线程设置 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();
         ...
    }
}
于 2012-08-30T02:54:17.780 回答