Java has implemented two ways of doing this: by blocking methods (which you have already addressed) or by non-blocking methods.
For the easiest way to get to asynchronous communication by blocking methods you can take a look at this answer:
question 1041014
If you want to use non-blocking methods, you have to take a look at the NIO framework. It is not particularly easy to implement in the beggining because it uses several complicated concepts, but once you get to understand how to handle the communication events it is pretty simple to make powerfull implementations. At the end you will end up using blocking methods because the CPU time is unnecesary to waste, but the NIO framework will let you create a single thread communication implementation which will be very optimal for cpu and memory usages.
Take a look at the O'reilly NIO book.