Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SingleThreadModel已被弃用,不能保证线程安全,在Servlet中保证线程安全的最佳解决方案/设计方法是什么?_Java_Servlets_Thread Safety_Singlethreadmodel - Fatal编程技术网

Java SingleThreadModel已被弃用,不能保证线程安全,在Servlet中保证线程安全的最佳解决方案/设计方法是什么?

Java SingleThreadModel已被弃用,不能保证线程安全,在Servlet中保证线程安全的最佳解决方案/设计方法是什么?,java,servlets,thread-safety,singlethreadmodel,Java,Servlets,Thread Safety,Singlethreadmodel,我想在我的Servlet中保证线程安全SingleThreadModel已弃用,不能保证线程安全。相反,我可以在我的Servlet中使用synchronized块 这是保证Servlet中线程安全的另一种方法吗 如果是,请说明如何实现 如果没有,我将采用什么设计方法来保证Servlet中的线程安全?Java Servlet没有什么特别之处,它或多或少会受到线程问题的影响,但是,由于web服务器的多线程特性,Java Servlet中可能存在的任何线程问题都会很快变得明显 我之所以这样说,是因为我

我想在我的
Servlet
中保证线程安全
SingleThreadModel
已弃用,不能保证线程安全。相反,我可以在我的
Servlet
中使用
synchronized

这是保证Servlet中线程安全的另一种方法吗

如果是,请说明如何实现


如果没有,我将采用什么设计方法来保证
Servlet
中的线程安全?

Java Servlet没有什么特别之处,它或多或少会受到线程问题的影响,但是,由于web服务器的多线程特性,Java Servlet中可能存在的任何线程问题都会很快变得明显

我之所以这样说,是因为我想强调一点,即Java servlet并不特殊。您可以轻松编写任何非线程安全的代码。在JavaServlet中很难做到这一点

构建应用程序的一种流行技术是将代码(逻辑上和物理上)分成三堆:建模(数据)model、view(UI)和ccontroller——通常缩写为“MVC”。当你这样做时,你认为“视图”和“控制器”是无状态的。也就是说,模型包含程序/用户/事务/任何内容的所有状态,控制器和视图只需根据需要修改该状态,并允许该模型在代码中流动

在servlet容器中,servlet本身是控制器(或视图),应该是无状态的。这很容易做到:不要使用任何包含用户或事务特定内容的类成员。任何Servlet类成员本身都必须是线程安全的(比如
ConcurrentMap
),或者以线程安全的方式使用(比如
同步的
块访问
HashMap
)。请记住,即使是线程安全的集合(例如,
ConcurrentMap
)也可以以非线程安全的方式使用,如下所示:

ConcurrentMap cm = ...;
if(!cm.containsKey("foo")) {
    cm.put("foo", createFoo());
}
上述代码无法阻止两个线程调用
createFoo
,这可能是一个代价高昂(或破坏性!)的操作。您需要使用同步块来避免两个线程之间的冲突

那么,你把模型放在哪里?嗯,你有几种选择。最简单的方法之一是将所有内容都保存在用户的
会话中。会话是一种特定于用户的结构,可通过所有
HttpServletRequest
对象访问,因此它始终可用于servlet。不过,这仅在用户实际登录到您的应用程序时有效。现在让我们假设您确实有用户,并且他们有自己的会话

会话根据发出请求的用户的身份自动与请求关联。您需要的任何其他数据都应该来自请求本身(可能是来自的请求参数)

您可以在会话中放入任何想要的内容。与包含其他
Map
s、
列表的命名集合的
Map
对象相比,描述“业务对象”(您用于表示特定应用程序中概念的东西)的自定义类更可取,我见过完整的web应用程序只使用标准Java库类构建,它们是一堆地图查找和魔法列表索引。不要落入这个陷阱:编写自己的类

用户模型数据的另一种选择是将其存储在某种数据库中。“数据库”有许多选项,从简单的文件存储到关系数据库再到文档/列/索引存储。他们都有自己的长处和短处。但它们存储数据,您可以将用户模型数据放入数据库。您如何识别用户?可能是通过在会话中存储用户id。(所以通常都会回到会话中)。您还可以使用用户的用户名(可从请求中获得)在数据库中查找用户的数据

在任何情况下,您都不应该在servlet的类成员中存储关于用户状态(包括工作流等)的任何信息。如果您避免这样做,那么您就不必担心servlet中的线程安全了


另一个问题是共享资源的问题。这个问题的解决方案是确保以线程安全的方式使用这些共享资源。通常可以使用池资源(如数据库连接池、消息队列、搜索索引等)来解决这些问题。解决这些问题通常与共享的资源类型有关,因此,当您进入该阶段时,您可能想问一个更具体的问题。

实际上,Java中提供的所有确保线程安全的机制都可用于servlet<代码>同步
块就是其中之一。避免可变共享数据是另一个问题。包
java.util.concurrent
及其子包中有更多内容。也可能有其他适用的。哪一个最适合你的特定目的取决于你想做什么的细节。