在耗時較長的Controller中使用Future異步

有一些Controller要算一些東西,可能會耗時較長,咱們以休眠2秒來模擬這個過程。服務器

代碼以下app

public class Dog implements Serializable {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
@RestController
public class DogController {
    @GetMapping("/getdog")
    public Dog getDog() throws InterruptedException {
        Dog dog = new Dog();
        dog.setName("mimi");
        dog.setAge(1);
        Thread.sleep(2000);
        return dog;
    }
    @GetMapping("/syncgetdog")
    public Callable<Dog> syncGetDog() {
        Callable<Dog> dog = new Callable<Dog>() {
            @Override
            public Dog call() throws Exception {
                Dog midog = new Dog();
                midog.setName("mimi");
                midog.setAge(1);
                Thread.sleep(2000);
                return midog;
            }
        };
        return dog;
    }
}

這裏咱們使用了兩種方式來獲取一條狗的名字和年齡。第一種是最傳統的單線程返回。第二種採用了Future模式的異步返回。咱們對性能進行一次壓測,壓測的線程數1000,循環5次,共5000次。異步

咱們先來壓第一個getdogide

壓測結果以下性能

經過該結果咱們能夠看到吞吐量爲96.9,最小響應時間2秒6,最大響應時間10秒3(固然這是我本機的壓測,非服務器,數值量會偏小)this

而後咱們對異步調用進行壓測線程

壓測結果以下blog

吞吐量379.2,最小響應時間2秒,最大響應時間3秒。get

緣由主要在於單線程的程序一條道走到黑,不運行完毫不撒手,Tomcat的可用線程被徹底霸佔。而Future模式的異步調用則是另外啓動一個線程將Callable交給TaskExecutor去處理,Tomcat本身的主線程退出,去從新接收其餘的請求調用,等到Callable執行結束後,就會從新啓動分配一個request請求,調用和處理Callable異步執行的返回結果,而後最終返回結果。io

但這裏有一點須要說明,當一個請求處理及其短期的時候,不要使用Future模式的異步調用,性能反而不如單線程模式。

相關文章
相關標籤/搜索