在正常的業務中使用同步線程,若是服務器每處理一個請求,就建立一個線程的話,會對服務器的資源形成浪費。由於這些線程可能會浪費時間在等待網絡傳輸,等待數據庫鏈接等其餘事情上,真正處理業務邏輯的時間很短很短,可是其餘線程在線程池滿了以後又會阻塞,等待前面的線程處理完成。並且,會出現一個奇怪的現象,客戶端的請求被阻塞,可是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