Network Programming: Blocking & Non-blocking, Synchronous & Asynchronous
This could be one of the concepts that will easily get confused, especially for those ones just get started on network programming.
The Major Difference
First thing: blocking operation does NOT equal to synchronous, also non-blocking operation does NOT equal to asynchronous. Actually, they don't have direct relevant with each other.
Synchronous & Asynchronous
Synchronous/asynchronous describes the communication mechanism.
Synchronous is, when we started a function call, the call will not return anything until it gets the result, the function needs to finish everything before it can give anything to us.
Asynchronous does not need to wait for the function completes its operation, once we call it, it returns immediately without any result, the function uses callback function (or other notification method) to "notify" us to get the value after it completes execution.
A Common "Noob" Problem: Why I get null
from my getter?
Before we continue, let's take a look at this getter from an android project:
public class CarService {
public Car getCar() {
...
client.get("https://car.example/api", params, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] res) {
try {
String result = new String(res, "utf-8");
Gson gson = new GsonBuilder().create();
car = gson.fromJson(result, Car.class);
} catch (UnsupportedEncodingException e) {
Log.e("Error", e.getMessage());
}
}
@Override
public void onFailure(int statusCode, Header[] headers, byte[] res, Throwable error) {
Log.e("Request Error", String.valueOf(statusCode));
}
});
return car;
}
}
Looks like it has no problem: it establishes an API call to get the car from server, and returns it at the end. However, when this getter gets called in another class:
public CarActivity extends Activity {
private Car myCar;
private CarService carService;
//.....
public void setMyCar() {
myCar = carService.getCar(); // <- *this will return null*
}
}
myCar
will be null
, why? Because the getter starts an async operation AsyncHttpResponseHandler()
to establish an API call asynchronously and returns car
immediately right after that, the function will not wait for the inside code (onSuccess()
, onFailure()
, etc) to finish, so car
gets returned before it gets the value from the server.
So how to solve it? A straight forward solution is to use a callback to handle the response instead of just return it:
public interface CarServiceCallBack {
void onSuccess(Car car);
}
In class CarService
:
public void getCar(final CarServiceCallback callback) {
client.get("https://car.example/api", params, new AsyncHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Header[] headers, byte[] res) {
try {
String result = new String(res, "utf-8");
Gson gson = new GsonBuilder().create();
car = gson.fromJson(result, Car.class);
callback.onSuccess(car); // <- Pass the car object to callback funtion
} catch (UnsupportedEncodingException e) {
Log.e("Error", e.getMessage());
}
}
...
}
}
And in CarActivity.setMyCar()
:
public void setMyCar() {
// Construct a new callback object
carService.getCar(new CarServiceCallback() {
@Override
public void onSuccess(Car car) {
myCar = car; // <- pass the received car object to myCar
}
});
}
How this works? When CarActivity.setMyCar()
gets called, it will call carSerivce.getCar()
and pass in a new callback interface CarServiceCallback
to handle the async operation, while the client successfully gets the response, in the handler's onSuccess()
it will ask the callback interface to call its onSuccess()
method, which is implemented in CarActivity.setMyCar()
:
public void onSuccess(Car car) {
myCar = car; // <- pass the received car object to myCar
}
Blocking & Non-blocking
Unlike synchronous/asynchronous, blocking/non-blocking focuses on the status of the program while waiting for the result from the function call.
A blocking operation hangs up current thread before it gets the result, in other words, a blocking operation will let the current thread wait for the result returns, even if the target function will use a callback function to notify client side to fetch the result, the thread on the client side will still be blocked until it gets the returned result. In opposite way, the non-blocking operation will not hang up the current thread if no result returned immediately.
A Simple Example
You are the customer making the phone call to the hotel to make a reservation.
Synchronous: The hotel receptionist receives the call and ask you to wait while he/she needs to look up the calendar to see if there is any available time slot. After finished looking up, the receptionist tells you if the requested time slot is available (result returned).
Asynchronous: The hotel receptionist receives the call and tell you that they have got the information, then he/she hangs up, you will receive a call back from the hotel once they have finished checking (callback).
Blocking: You make the phone call, before you get any result back, you will sit on the couch and do nothing until the hotel tells you if your reservation can be made.
Non-blocking: You make the phone call, after telling the information to the hotel, you start to do something else (drink water, eat snacks, take shower, etc.) and check if you get any results every few minutes.
Overall
The example above should give you a clear understanding of the underlying communication between client (you) and server (hotel). Sync/Async usually describes how the server will deal with incoming requests, and Blocking/Non-blocking describes how the client side will handle the results (wait or do something else).
Further Reading:
Understanding Synchronous vs Asynchronous (AJAX) - JavaTPoint
Blocking and Nonblocking I/O - Kansas State Polytechnic