1. 程式人生 > >認識非同步、非阻塞、futrue、callback

認識非同步、非阻塞、futrue、callback

高併發、大訪問量實際是程式猿界的分水嶺,如何從各個角度去解決這些問題?這也是面試的時候架構師被問過的最多的問題。而非同步、非阻塞對於效能的提升是每個武林高手的錦囊妙計。

非同步和非阻塞是什麼關係?什麼區別?

此問題一出,可以直接鑑別真偽,不信你問下試試~哈哈!!!看完此文,相信你就清楚了。

非同步毫無疑問,就是啟動多個執行緒,讓每個執行緒去做一部分工作,互不干擾。

當需要匯聚結果的時候,必須採用futrue的模式。簡單來講,就是當你用多執行緒非同步的去執行的時候,如果不需要知道結果,可以直接結束。但是當你需要知道結果的時候,最好採用callablefutrue配合完成。例如,如果對使用者表進行了水平切分,需要從多個表查詢資料時,就可以採用這種方式。

Futrue就是你需要得到的結果。它代表的是未來,因為是非同步,future.get()不一定有結果,如果你去get的時候還沒有結果,是會被阻塞的。但是在你必須獲取結果之前,還可以做很多事情,這時候是不受影響的。是非阻塞的狀態。

Future模式需要通過輪訓或阻塞等待的方式,才能得到結果。這樣總是顯得不太優雅,比較好的方式應該是callback(回撥函式,寫過ajax的肯定比較清楚)的方式,也就是執行結束的時候非同步通知完成狀態。然後再去futrue中取執行結果。

實際上futruecallback這種經典的模型在很多語言裡都有了原生的支援,jdk中雖然有futrue,但是並不支援

callback模式。還好guava給我們又打開了一扇窗——ListenableFuture在jdk8中已經得到了完善。找個時間再寫寫。

非同步、非阻塞給你帶來的問題就是除錯的麻煩,程式設計複雜度的提升,不過有了這些工具類,變得簡單了很多。如果公司有開發框架的話,可以直接封裝在底層。

直接上程式碼,可以仔細看下注釋,你就明白整個過程了。

public class FutureExample {
   public static void main(String[] args) throws

 Exception {
       // jdk自帶Future模式,實現非同步,交給執行緒池處理任務
      ExecutorService jdkExecutor =Executors.newSingleThreadExecutor();
       Future<String> jdkFuture = jdkExecutor
               .submit(new Callable<String>() {
                   @Override
                   public String call() throws Exception {
                      // 模擬業務消耗時間

                   TimeUnit.SECONDS.sleep(100);
                      return "This is native future call.not supportasync callback";
                   }
              });
       // Future只實現了非同步,而沒有實現回撥.所以此時主執行緒get結果時阻塞.或者可以輪訓以便獲取非同步呼叫是否完成,提交到執行緒池到get結果之間是非阻塞的,可以處理其他任務。
      System.out.println(jdkFuture.get());
       // 好的實現應該是提供回撥,即非同步呼叫完成後,可以直接回調.本例採用guava提供的非同步回撥介面,方便很多.
      ListeningExecutorService guavaExecutor = MoreExecutors
              .listeningDecorator(Executors.newSingleThreadExecutor());
       final ListenableFuture<String>listenableFuture = guavaExecutor
               .submit(new Callable<String>() {
                   @Override
                   public String call() throws Exception {
                      Thread.sleep(1000);
                      return "this is guava future call.support asynccallback";
                   }
              });
       // 註冊監聽器,即非同步呼叫完成時會在指定的執行緒池中執行註冊的監聽器
      listenableFuture.addListener(new Runnable() {
           @Override
           public void run() {
               try {
                                             System.out.println("async complete.result:"+ listenableFuture.get());
                                          } catch (Exception e) {
               }
          }
      }, Executors.newSingleThreadExecutor());
       // 主執行緒可以繼續執行,非同步完成後會執行註冊的監聽器任務.
      System.out.println("go on execute.asyn complete willcallback");
       // 除了ListenableFuture,guava還提供了FutureCallback介面,相對來說更加方便一些.
      ListeningExecutorService guavaExecutor2 = MoreExecutors
              .listeningDecorator(Executors.newSingleThreadExecutor());
       final ListenableFuture<String>listenableFuture2 = guavaExecutor2
               .submit(new Callable<String>() {
                   @Override
                   public String call() throws Exception {
                      Thread.sleep(1000);
                      System.out.println("asyncThreadName:"
                              + Thread.currentThread().getName());
                      return "this is guava future call.support asynccallback using FutureCallback";
                   }
              });
       // 注意這裡沒用指定執行回撥的執行緒池,從輸出可以看出,預設是和執行非同步操作的執行緒是同一個.當然也可以再起一個執行緒池,取決於處理的複雜度,和相互之間的影響。
      Futures.addCallback(listenableFuture2, new FutureCallback<String>() {
           @Override
           public void onSuccess(String result) {
               System.out
                      .println("async callback(using FutureCallback) result:"
                              + result);
              System.out.println("execute callback threadName:"
                      + Thre           }ad.currentThread().getName());
           @Override
           public void onFailure(Throwable t) {
           }
       });
 }
}



參考文獻:

http://www.blogjava.net/landon/archive/2014/02/27/410387.html(程式碼)

http://ifeve.com/google-guava-listenablefuture/


更多文章歡迎關注我的微信公眾號,奔跑中的蝸牛,可以掃描頭像關注