简体   繁体   English

多线程访问Java中的同一对象

[英]Multiple threads accessing the same object in Java

I am building a web server using the HttpSevlet in Java. 我正在使用Java中的HttpSevlet构建Web服务器。 I created an ABSTRACT class named BaseApi which extends HttpSevlet and this serves as the parent class. 我创建了一个名为BaseApiABSTRACT类,该类扩展了HttpSevlet并将其用作父类。

Everytime the doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException of BaseApi is called. 每次doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException BaseApi的 doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException 被调用。 a new BaseRequest is instantiated. 实例化一个新的BaseRequest BaseRequest is just another class that I created and is a member of BaseApi . BaseRequest只是我创建的另一个类,并且是BaseApi的成员。

public abstract class BaseApi extends HttpServlet
{
    private static final long serialVersionUID = 6333682258528494467L;

    protected BaseRequest request;
}

Then I have a child class, DeviceList which extends the BaseApi, and DeviceListRequest which extends BaseRequest 然后,我有一个子类,DEVICELIST扩展了BaseApi和DeviceListRequest延伸BaseRequest

public class DeviceList extends BaseApi

public class DeviceListRequest extends BaseRequest

The problem is this. 问题是这样的。 Everytime the doGet method of DeviceList is called I THINK that a new thread is created. 每次DEVICELIST的doGet方法被称为我认为一个新的线程被创建。 Well, I made 2 concurrent requests and the log looks like this. 好吧,我发出了2个并发请求,日志看起来像这样。

[2017-10-18 02:06:39,760] INFO  Thread:Thread[http-nio-8080-exec-8,5,main] Instance:server.request.DeviceListRequest@2f15bbce retCode:-3
[2017-10-18 02:06:39,761] INFO  Thread:Thread[http-nio-8080-exec-7,5,main] Instance:server.request.DeviceListRequest@5343acea retCode:-3

Well, don't mind the retCode thing, just focus on the Thread: and Instance: . 好吧,不要介意retCode,只关注Thread:Instance: :。 I am not sure if Thread[http-nio-8080-exec-8,5,main] and Thread[http-nio-8080-exec-7,5,main] are two different threads. 我不确定Thread[http-nio-8080-exec-8,5,main]Thread[http-nio-8080-exec-7,5,main]是两个不同的线程。 Because there's a word MAIN there. 因为那里有一个词。 and I don't know if there can be two main threads. 而且我不知道是否可以有两个主线程。 Or if this really is the main thread. 或者,如果这确实是主线程。

So, based on the logs. 因此,基于日志。 I think that there are two Threads created and two different instances of DeviceListRequest created DeviceListRequest@2f15bbce and DeviceListRequest@5343acea . 我认为有创建两个线程,创建DeviceListRequest @ 2f15bbceDeviceListRequest @ 5343acea DeviceListRequest的两个不同的实例。

Now, as the code continues to run, I notice that the Threads began to access two DeviceListRequest interchangeably. 现在,随着代码继续运行,我注意到线程开始可互换地访问两个DeviceListRequest Here's the rest of the logs 这是其余的日志

[2017-10-18 02:06:39,760] INFO  Thread:Thread[http-nio-8080-exec-8,5,main] Instance:server.request.DeviceListRequest@2f15bbce retCode:-3
[2017-10-18 02:06:39,761] INFO  Thread:Thread[http-nio-8080-exec-7,5,main] Instance:server.request.DeviceListRequest@5343acea retCode:-3
[2017-10-18 02:06:39,765] INFO  Thread:Thread[http-nio-8080-exec-8,5,main] Instance:server.request.DeviceListRequest@2f15bbce retCode:0
[2017-10-18 02:06:39,765] INFO  Thread:Thread[http-nio-8080-exec-8,5,main] Instance:server.request.DeviceListRequest@2f15bbce setResponseObjectWithKey->serverResponse:{"devices":[]} serverResponse_id:636342462
[2017-10-18 02:06:39,765] INFO  Thread:Thread[http-nio-8080-exec-8,5,main] Instance:server.request.DeviceListRequest@5343acea 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:server.request.DeviceListRequest@5343acea retCode:0
[2017-10-18 02:06:39,766] INFO  Thread:Thread[http-nio-8080-exec-7,5,main] Instance:server.request.DeviceListRequest@5343acea 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:server.request.DeviceListRequest@5343acea serverResponse:{"devices":[],"ret_msg":"OK","ret_code":0} serverResponse_id:1626294887

Again, just look at the Thread: and Instance: 同样,只需查看Thread:和Instance:

Take a look at this two lines of logs from what I showed 看一下我显示的这两行日志

[2017-10-18 02:06:39,765] INFO  Thread:Thread[http-nio-8080-exec-8,5,main] Instance:server.request.DeviceListRequest@2f15bbce setResponseObjectWithKey->serverResponse:{"devices":[]} serverResponse_id:636342462
[2017-10-18 02:06:39,765] INFO  Thread:Thread[http-nio-8080-exec-8,5,main] Instance:server.request.DeviceListRequest@5343acea serverResponse:{"ret_msg":"unknown","ret_code":-3} serverResponse_id:1626294887

Thread Thread:Thread[http-nio-8080-exec-8,5,main] accessing objects DeviceListRequest@2f15bbce and DeviceListRequest@5343acea 线程Thread:Thread [http-nio-8080-exec-8,5,main]访问对象DeviceListRequest @ 2f15bbceDeviceListRequest @ 5343acea

NOTES: By the way, I am using System.identityHashCode(yourObject) to get the ID of the objects. 注意:顺便说一句,我正在使用System.identityHashCode(yourObject)来获取对象的ID。 And I am using Thread.currentThread() to get the thread identifier. 我正在使用Thread.currentThread()获取线程标识符。

My questions are as follows: 1. Are Thread[http-nio-8080-exec-8,5,main] and Thread[http-nio-8080-exec-7,5,main] two different threads? 我的问题如下:1. Thread [http-nio-8080-exec-8,5,main]Thread [http-nio-8080-exec-7,5,main]两个线程是否不同? 2. Are threads containing main in their names considered as main thread? 2.名称中包含main的线程是否被视为main线程? If yes, then why there is more than one main thread? 如果是,那么为什么会有多个主线程? 3. How can I avoid the problem that there are threads accessing the objects that were not created on it? 3.如何避免有线程访问未在其上创建的对象的问题?

Thanks! 谢谢!

These are different threads. 这些是不同的线程。 The servlet container has a Thread pool, threads from the pool will be assigned to http requests. Servlet容器具有一个线程池,该池中的线程将分配给http请求。 A servlet container is not prohibited from making more than one instance of a given servlet but usually there is only one. 禁止servlet容器制作一个给定servlet的多个实例,但通常只有一个。 You should expect servlets to be called concurrently from multiple threads. 您应该期望从多个线程同时调用servlet。

Don't let servlets keep mutable state. 不要让Servlet保持可变状态。 Any instance variable that is declared in a servlet should be Thread safe. 在Servlet中声明的任何实例变量都应该是线程安全的。 Making the servlet state relate to a given request is bound to be trouble. 使Servlet状态与给定请求相关必然会带来麻烦。 Keep state related to a request in local variables of the method. 将与请求相关的状态保留在方法的局部变量中。

  1. Are Thread[http-nio-8080-exec-8,5,main] and Thread[http-nio-8080-exec-7,5,main] two different threads? 线程[http-nio-8080-exec-8,5,main]和线程[http-nio-8080-exec-7,5,main]是两个不同的线程吗?

Yes, every request is going to run in a different thread. 是的,每个请求都将在不同的线程中运行。

  1. Are threads containing main in their names considered as main thread? 是否将名称中包含main的线程视为主线程? If yes, then why there is more than one main thread? 如果是,那么为什么会有多个主线程?

No, only the initial thread created on JVM start is considered the main thread. 不,只有在JVM启动时创建的初始线程才被视为主线程。 Any thread can be renamed and contain "main" in it's name. 任何线程都可以重命名并在其名称中包含“ main”。 The main you see in the log is probably the name of the ThreadGroup the actual names of the threads are http-nio-8080-exec-7 and http-nio-8080-exec-8. 您在日志中看到的主要名称可能是ThreadGroup的名称,实际的线程名称是http-nio-8080-exec-7和http-nio-8080-exec-8。

  1. How can I avoid the problem that there are threads accessing the objects that were not created on it? 如何避免有线程访问未在其上创建的对象的问题?

This is not always a problem, what happens in your case is that you store a DeviceListRequest in your Servlet and there is usually only one Servlet which is used for multiple requests. 这并不总是一个问题,在您的情况下,您会在DeviceListRequest中存储一个DeviceListRequest ,并且通常只有一个Servlet用于多个请求。 Instead you should use a local variable, pass it to methods if needed or if you're going to forward the request to another Servlet save it in the request. 相反,您应该使用局部变量,如果需要,或者如果您要将请求转发到另一个Servlet,则将其传递给方法,然后将其保存在请求中。

req.setAttribute("someName", new DeviceListRequest());

And then when you want to access it later do: 然后,当您以后想要访问它时,请执行以下操作:

req.getAttribute("someName");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM