Does Spring create new thread per request in rest controllers?

user picture user · Dec 22, 2017 · Viewed 10.4k times · Source

I wanted to learn non blocking REST, but first I wrote blocking controller for comparison. To my surprise Spring doesn't block incoming requests.

Simple blocking service:

@Service
public class BlockingService {

    public String blocking() {
        try {
            Thread.sleep(10000L);
        } catch (InterruptedException ign) {}
        return "Blocking response";
    }
}

Simple REST controller:

@Slf4j
@RestController
public class BlockingRestController {

    private final BlockingService blockingService;

    @Autowired
    public BlockingRestController(BlockingService blockingService) {
        this.blockingService = blockingService;
    }

    @GetMapping("blocking")
    public String blocking() {
        log.info("Starting blocking request processing...");
        return blockingService.blocking();
    }
}

And I was thinking that when I send 4 requests using curl from 4 separated terminals I get:

1. Starting blocking request processing... (console where spring is running)
2. (4 terminals waiting)
3. "Blocking response" (in 1st terminal)
4. Starting blocking request processing... (console where spring is running)
5. (3 terminals waiting)
6. "Blocking response" (in 2nd terminal)
And so on...

But to my surprise I got:

1. Starting blocking request processing... (console where spring is running)
2. Starting blocking request processing... (console where spring is running)
3. Starting blocking request processing... (console where spring is running)
4. Starting blocking request processing... (console where spring is running)
5. "Blocking response" (in 1st terminal)
6. "Blocking response" (in 2nd terminal)
7. "Blocking response" (in 3rd terminal)
8. "Blocking response" (in 4th terminal)

Why first request doesn't block processing requests? Yet I don't create new threads and I don't process anything asynchronous?

Why do I ask about it? Because I want to learn how to use DeferredResult, but now I don't see a need.

Answer

JB Nizet picture JB Nizet · Dec 22, 2017

It's blocking in the sense that it blocks one thread: the thread taken out of the pool of threads by the servlet container (Tomcat, Jetty, etc., not Spring) to handle your request. Fortunately, many threads are used concurrently to handle requests, otherwise the performance of any Java web application would be dramatic.

If you have, let's say, 500 concurrent requests all taking 1 minute to complete, and the pool of threads has 300 threads, then 200 requests will be queued, waiting for one of the threads to become available.