简体   繁体   中英

Multiple threads accessing the same object in Java

I am building a web server using the HttpSevlet in Java. I created an ABSTRACT class named BaseApi which extends HttpSevlet and this serves as the parent class.

Everytime the doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException of BaseApi is called. a new BaseRequest is instantiated. BaseRequest is just another class that I created and is a member of 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

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. Well, I made 2 concurrent requests and the log looks like this.

[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: . 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. 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 .

Now, as the code continues to run, I notice that the Threads began to access two DeviceListRequest interchangeably. 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:

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

NOTES: By the way, I am using System.identityHashCode(yourObject) to get the ID of the objects. And I am using Thread.currentThread() to get the thread identifier.

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? 2. Are threads containing main in their names considered as main thread? 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?

Thanks!

These are different threads. The servlet container has a Thread pool, threads from the pool will be assigned to http requests. A servlet container is not prohibited from making more than one instance of a given servlet but usually there is only one. You should expect servlets to be called concurrently from multiple threads.

Don't let servlets keep mutable state. Any instance variable that is declared in a servlet should be Thread safe. Making the servlet state relate to a given request is bound to be trouble. 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?

Yes, every request is going to run in a different thread.

  1. Are threads containing main in their names considered as main thread? 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. Any thread can be renamed and contain "main" in it's name. 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.

  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. 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.

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

And then when you want to access it later do:

req.getAttribute("someName");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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