views:

155

answers:

2

Hi,

Is HttpUrlConnection thread safe? I.e. if I have an HttpConnection instance connected to a server and this instance is used by different threads (e.g.try to send a POST concurrently) how will this situation be handled by HttpUrlConnection? a) Will they send the POSTs serially, or b) the first thread sends the POST, gets the response and then the second thread will send the POST? If they send the POSTs serially, this means multiple active POSTs to the same tcp connection. Is this allowed? Can it be handled by a server?

Thanks

A: 

it's not thread safe.

you shouldn't cache/share a connection. just create a new connection for each request. there is certainly a little overhead in creating new connections, but it is very small, you shouldn't worry about it.

the spirit of HTTP is actually connection-less. there is no, semantically speaking, connection between client and server. client sends a request, server sends back a response, that is all.

although today HTTP is indeed defined on top of TCP, which is a connection-ful protocol, and HTTP may use long lived TCP connection for multiple requests/responses, that's not the nature of HTTP.

since a request-response exchanged can be implemented on top of most network protocols, originally HTTP allowed possibility of specifying underlying protocols. We can imagine http request/response exchange over email - http:/smtp/www.example.com; maybe RMI - http:/rmi/www.example.com; the default is TCP, so http:// really means http:/tcp/

today, only TCP is used, and we are left with this curious double slash separator. but it's a reminder that HTTP's dependency on TCP is rather incidental.

irreputable
I understand what you are saying. But isn't your advice on creating a new connection per request an HTTP1.0 approach? Also by saying I shouldn't cache a connection, you effectively mean to avoid connection pooling schemes? My intention was to reuse an established connection through multiple requests to avoid the 3-way handshake overhead. Additionally I was wondering if I could "push" multiple POST requests over the same tcp connection. Am I completely off-track?
if you really care about performance, open a raw TCP connection, and write to it your requests. Try it, it is surprisingly simple, as HTTP is a simple design. You may have multiple threads writing to the same TCP connection, however then you need to synchronize so that only one thread does it at a time. You are better off with one connection per thread. If you have multiple connections open to a server, your throughput will likely be improved.
irreputable
When you say "multiple threads writing to the same TCP connection, however then you need to synchronize so that only one thread does it at a time" you mean each thread sends the POST and gets the response and then the next thread takes the TCP connection? I am sorry but it is not clear to me how using the raw tcp connection is an improvement over using httpurlconnection? Why not just synchronize the httpurlconnection access? Would you be kind to please explain this more?
+1  A: 

It does not say if it is or not in the docs. After looking at the code ( http://www.java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-sun/net/sun/net/www/protocol/http/HttpURLConnection.java.htm ) it looks like getInputStream and getOutputStream are synchronized. The concern I do have is that if you have a Thread that gets an input Stream and at the same time you have another Thread that gets an Output Stream you might get your signals crossed. inputStream and outputStream are instance variables that probably should not be shared across Threads.

If I were you I would implement a queue that would allow you to post the messages to the queue and would then post them to the server one at a time. When the request returns then you simply invoke a callback. This would make sure that a request was not sent before a response came back.

Romain Hippeau
What you say makes a lot of sense. I was wondering though, If instead of the worse case with signal crossing we had the following: thread1 and thread2 share httpurlconnection. Both threads try to do a POST. Thread2 would block since the getOutputStream is synchronized. Thread1 finishes writing the request and locks the input stream for the result. Thread2 gets the output stream and writes the POST. Then thread2 blocks in the inputstream. At this point there are 2 active POSTs in the same tcp connection. Is there any chance a server could handle this? So that the responses come in proper order?
@user384706 The documentation does not say that it is Thread safe, the code says that only certain parts are synchronized and that you would need to add a layer on top to make it Thread safe. By doing it yourself you are running a heavy risk, if it fails you will have a hard time figuring out the issues. If I were you I would look at an implementation that is documented as being Thread Safe such as http://hc.apache.org/httpclient-3.x/threading.html and not have to worry about it.
Romain Hippeau