在正常的業務中使用同步線程,如果服務器每處理一個請求,就創建一個線程的話,會對服務器的資源造成浪費。因為這些線程可能會浪費時間在等待網絡傳輸,等待數據庫連接等其他事情上,真正處理業務邏輯的時間很短很短,但是其他線程在線程池滿了之后又會阻塞,等待前面的線程處理完成。而且,會出現一個奇怪的現象,客戶端的請求被阻塞,但是cpu的資源使用卻很低,大部分線程都浪費在處理其他事情上了。所以,這就導致服務器並發量不高。
而異步,則可以解決這個問題。
我們可以把需要用到cpu的業務處理使用異步來實現,這樣其他請求就不會被阻塞,而且cpu會保持比較高的使用率。
今天就學習了使用回調來實現異步的方法。我們設想一個情景,A是處理業務的一個步驟,A需要解決一個問題,這時候A可以問B,讓B來告訴A答案,這期間,A可以繼續做自己的事情,而不用因為B做的事而阻塞。於是,我們想到給B設置一個線程,讓B去處理耗時的操作,然后處理完之后把結果告訴A。所以這個問題的要點就在於B處理完之后如何把結果告訴A。我們可以直接在A中寫一個方法對B處理完的結果進行處理,然后B處理完之后調用A這個方法。這樣A調用B去處理過程,B調用A的C方法去處理結果就叫做回調。
1 package CallBack; 2 3 public interface CallBack { 4 /* 5 *A處理結果的方法,為什么要寫這個接口呢? 6 *因為可能不止A需要用到B的處理過程,如果很多地方需要用到B 7 * 那么傳入B的方法就不可能只傳A類,所以要定義一個接口, 8 * 傳入B的處理方法的參數就是這個接口對象 9 * */ 10 public void solve(String result); 11 }
1 package CallBack; 2 3 public class A implements CallBack { 4 private B b; 5 6 public A(B b){ 7 this.b=b; 8 } 9 10 //A需要解決一個問題,所以他把問題交給B處理,B單獨創建一個線程,不影響A的運行 11 public void ask(final String question){ 12 System.out.println("A問了B一個問題"); 13 new Thread(()->{ 14 //B想要幫A處理東西,就必須知道誰讓自己處理的,所以要傳入a,也要知道a想處理什么,所以要傳入question 15 b.executeMessage(A.this,question); 16 }).start(); 17 //A把要處理的事情交給b之后,就可以自己去玩耍了,或者去處理其他事情 18 play(); 19 } 20 21 public void play(){ 22 System.out.println("我要逛街去了"); 23 } 24 25 //A拿到了B處理完成的結果,可以進行一些操作,比如把結果輸出 26 @Override 27 public void solve(String result) { 28 System.out.println("B告訴A的答案是--》"+result); 29 } 30 31 }
1 package CallBack; 2 3 public class B { 4 public void executeMessage(CallBack callBack,String question){ 5 System.out.println(callBack.getClass()+"問的問題--》"+question); 6 try { 7 Thread.sleep(3000); 8 } catch (InterruptedException e) { 9 e.printStackTrace(); 10 } 11 String result="答案是2"; 12 callBack.solve(result); 13 } 14 }
1 package CallBack; 2 3 public class test { 4 public static void main(String[] args) { 5 B b=new B(); 6 A a=new A(b); 7 a.ask("1+1=?"); 8 } 9 }
運行結果: A問了B一個問題 我要逛街去了 class CallBack.A問的問題--》1+1=? B告訴A的答案是--》答案是2 Process finished with exit code 0
