Tomcat线程和Java线程的区别

23
在使用Java线程时,通过同步等方式要注意并发带来的基本问题。
据我所知,Tomcat也使用线程来处理其工作负载。为什么当我的代码在Tomcat中运行时不必考虑使其线程安全呢?
4个回答

42

在Tomcat中,您确实需要使您的代码线程安全。Tomcat将从多个线程调用您的代码(即您的servlet),如果该代码不是线程安全的,您将会遇到问题。

Tomcat的线程与您自己创建的任何线程没有区别。


11
例如,当你编写一个servlet时,不应该在servlet类中使用局部变量。为什么呢?因为servlet类并非为每个线程实例化。Tomcat会重用实例来处理多个线程,所以所有变量都应该在doGet或doPost方法中,这样它们在每次调用方法时都会被初始化并分配到不同的内存位置。 - pakore
13
您好,@pakore的意思是说方法内部的变量是局部变量,您的意思应该是实例变量。 - Michael Borgwardt
1
是的,我的意思是实例变量。抱歉。谢谢你的纠正 :)。 我现在无法编辑我的评论 :(。 - pakore
这是真的吗?它不会创建一个新的线程,但也不会创建实现servlet的类的新实例吗?(我在grails、tomcat中尝试过,似乎实例变量没有问题) - csviri

25

除了skaffman提到的内容之外,当编写Web应用程序时,似乎不需要考虑多线程,因为Servlet框架/API完全是围绕实现方法(service(), doGet(), doPost()等)来进行的,这些方法在每个HTTP请求中触发一次。

因此,在简单应用程序中,您可以在您的Servlet和/或JSP中实现这些方法,并且不必考虑多个线程交互的情况。

但是,一旦在Servlet或服务方法之间存在共享状态,那么如果没有意识到,您将会涉及到多个线程相互交互的问题。如果您不小心处理,最终将会出现多线程或同步问题。您必须处理这个问题,因为在Tomcat(我假设所有Servlet容器都是这样,尽管我不知道Servlet规范是否要求如此)中,每个请求都由(可能)不同的线程处理。因此,如果您收到两个同时请求,这些请求将由两个不同的线程并发处理(即同时处理)。


6
如果你认为Tomcat可以使你的应用程序线程安全,那么写一个带有可变成员变量的Servlet,比如一个非并发的哈希映射表。
然后让这个Servlet在每个请求中把东西放在哈希映射表中。很快就会出现美妙的并发异常。 这就是为什么对于单例组件,你必须非常小心地处理成员变量,因为它们在多个访问对象的线程之间共享。 现在,如果Servlet容器为每个请求创建一个新的瞬态对象(这是一些Web应用程序框架所做的),你可以将与成员变量交互的行为放在该瞬态对象中,并实现线程安全。

0

由于Java EE容器是以处理线程的方式编写的,因此它们会为您处理线程。您编写的代码应该是线程安全的,容器会自动完成其余部分。它会池化线程并在请求到达时为每个请求分配一个线程。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接