多线程访问Java中的同一对象
我正在使用Java中的HttpSevlet
构建一个Web服务器。我创建了一个摘要类名为BaseApi它扩展了HttpSevlet
并且这作为父类。多线程访问Java中的同一对象
每次doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException
的BaseApi被调用。实例化新的BaseRequest。 BaseRequest是我创建的另一个类,它是BaseApi的成员。
public abstract class BaseApi extends HttpServlet
{
private static final long serialVersionUID = 6333682258528494467L;
protected BaseRequest request;
}
然后,我有一个子类,DEVICELIST延伸的BaseApi和DeviceListRequest延伸BaseRequest
public class DeviceList extends BaseApi
public class DeviceListRequest extends BaseRequest
问题是这样的。每次DeviceList的doGet方法被称为I THINK,即创建一个新线程。那么,我做了2个并发请求,日志看起来像这样。
[2017-10-18 02:06:39,760] INFO Thread:Thread[http-nio-8080-exec-8,5,main] Instance:[email protected] retCode:-3
[2017-10-18 02:06:39,761] INFO Thread:Thread[http-nio-8080-exec-7,5,main] Instance:[email protected] retCode:-3
好了,不介意RETCODE的事情,只是专注于Thread:
和Instance:
。我不确定Thread[http-nio-8080-exec-8,5,main]
和Thread[http-nio-8080-exec-7,5,main]
是两个不同的线程。因为那里有一个词MAIN。我不知道是否可以有两个主线。或者如果这真的是主线。
因此,基于日志。我认为有创建两个线程,2f15bbce和DeviceListRequest创建DeviceListRequest @的两个不同的实例DeviceListRequest @ 5343acea。
现在,随着代码的继续运行,我注意到线程开始交替访问两个DeviceListRequest。这里的日志
[2017-10-18 02:06:39,760] INFO Thread:Thread[http-nio-8080-exec-8,5,main] Instance:[email protected] retCode:-3
[2017-10-18 02:06:39,761] INFO Thread:Thread[http-nio-8080-exec-7,5,main] Instance:[email protected] retCode:-3
[2017-10-18 02:06:39,765] INFO Thread:Thread[http-nio-8080-exec-8,5,main] Instance:[email protected] retCode:0
[2017-10-18 02:06:39,765] INFO Thread:Thread[http-nio-8080-exec-8,5,main] Instance:[email protected] setResponseObjectWithKey->serverResponse:{"devices":[]} serverResponse_id:636342462
[2017-10-18 02:06:39,765] INFO Thread:Thread[http-nio-8080-exec-8,5,main] Instance:[email protected] serverResponse:{"ret_msg":"unknown","ret_code":-3} serverResponse_id:1626294887
[2017-10-18 02:06:39,766] INFO Thread:Thread[http-nio-8080-exec-7,5,main] Instance:[email protected] retCode:0
[2017-10-18 02:06:39,766] INFO Thread:Thread[http-nio-8080-exec-7,5,main] Instance:[email protected] setResponseObjectWithKey->serverResponse:{"devices":[],"ret_msg":"unknown","ret_code":-3} serverResponse_id:1626294887
[2017-10-18 02:06:39,766] INFO Thread:Thread[http-nio-8080-exec-7,5,main] Instance:[email protected] serverResponse:{"devices":[],"ret_msg":"OK","ret_code":0} serverResponse_id:1626294887
的休息再次,只是看在主题:和实例:
在日志的这两条线看看,我表明
[2017-10-18 02:06:39,765] INFO Thread:Thread[http-nio-8080-exec-8,5,main] Instance:[email protected] setResponseObjectWithKey->serverResponse:{"devices":[]} serverResponse_id:636342462
[2017-10-18 02:06:39,765] INFO Thread:Thread[http-nio-8080-exec-8,5,main] Instance:[email protected] serverResponse:{"ret_msg":"unknown","ret_code":-3} serverResponse_id:1626294887
主题螺纹螺纹[HTTP-NIO-8080-EXEC-8,5,主]访问对象DeviceListRequest @ 2f15bbce和DeviceListRequest @ 5343acea
注意:顺便说一下,我使用System.identityHashCode(yourObject)
来获取对象的ID。我正在使用Thread.currentThread()
来获取线程标识符。我的问题如下: 1。是线程[http-nio-8080-exec-8,5,主要]和线程[http-nio-8080-exec-7,5,主要]两个不同的线程? 2.包含名称中main的线程是否被认为是主线程?如果是,那么为什么有多个主线程? 3.如何避免线程访问没有创建的对象的问题?
谢谢!
- 是线程[HTTP-NIO-8080-EXEC-8,5,主]和线程[HTTP-NIO-8080-EXEC-7,5,主]两个不同的线程?
是的,每个请求都将运行在不同的线程中。
- 是否在主名称中包含名为main的线程?如果是,那么为什么有多个主线程?
不,只有在JVM启动时创建的初始线程才被认为是主线程。任何线程都可以重命名,并在其名称中包含“main”。您在日志中看到的主要可能是ThreadGroup
的名称,线程的实际名称是http-nio-8080-exec-7和http-nio-8080-exec-8。
- 如何避免线程访问未创建的对象的问题?
这并不总是一个问题,会发生什么你的情况是,你存储在你的servlet一个DeviceListRequest
,通常只有一个被用于多个请求的Servlet。相反,您应该使用本地变量,将其传递给方法(如果需要的话),或者如果您要将请求转发给另一个将其保存在请求中的Servlet。
req.setAttribute("someName", new DeviceListRequest());
然后当你要访问它以后做:
req.getAttribute("someName");
这些是不同的主题。 servlet容器有一个线程池,池中的线程将被分配给http请求。一个servlet容器不允许创建给定servlet的多个实例,但通常只有一个实例。您应该期望从多个线程同时调用servlet。
不要让servlet保持可变状态。任何在servlet中声明的实例变量都应该是线程安全的。使servlet状态与给定的请求相关将会遇到麻烦。通过方法的局部变量保持与请求相关的状态。
加一!谢谢(你的)信息! –