有一些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模式的異步調用,性能反而不如單線程模式。