<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## **主線程如何得知異步線程的執行結果?** 通過繼承Thread類或者實現Runnable接口方式創建的線程在執行后無法獲取執行結果,除非采用共享變量或者線程通信的方式獲得,但顯然這不是一種優雅的方式。Java中提供了使用Callable和Future來實現獲取任務結果的操作,Callable用來執行任務,產生結果,而Future用來獲得結果。 測試代碼 ``` // 通過實現Callable接口創建線程任務 class Task implements Callable<String> { @Override public String call() throws Exception { System.out.println("異步線程正在執行任務..."); Thread.sleep(3000); return "3000"; } } class test { public static void main(String[] args) throws ExecutionException, InterruptedException { // 創建線程池 ExecutorService executor = Executors.newCachedThreadPool(); Future<String> future = executor.submit(new Task()); System.out.println("主線程繼續執行"); // future獲取線程返回結果 String result = future.get(); System.out.println("主線程得到異步線程返回結果:" + result); executor.shutdown(); } } ``` 運行結果 ``` 主線程繼續執行 異步線程正在執行任務... 異步線程返回結果:3000 ``` ## **如何實現Future功能** 我們來模擬一個在主線程中進行遠程**異步**請求并且**得到請求響應的數據**的功能 * 異步:那自然是需要在主線程中開啟一個線程 * 得到異步響應的數據:就是我們下面要探討實踐的 1.創建遠程請求的抽象類 ``` public abstract class BaseRequest { // 獲取請求結果 public abstract String getResponse(); } ``` 2.創建實現具體請求的類 ``` public class SendRequest extends BaseRequest { // 最終返回的值 private String result; // 構造函數模擬發送耗時3秒的遠程請求 public SendRequest(String params) { System.out.println("正在讀取數據..."); ... Thread.sleep(3000); ... System.out.println("讀取數據完成..."); result = "hello"; } @Override public String getResponse() { return result; } } ``` 3.創建請求future類,目前來看這個類只是對SendRequest的簡單封裝,暫且沒多大意義。 ``` public class FutureRequest extends BaseRequest { private SendRequest sendRequest; public void sendRequest(SendRequest sendRequest) { this.sendRequest = sendRequest; } @Override public String getResponse() { return sendRequest.getResponse(); } } ``` 4.測試 ``` class test { public static void main(String[] args) { FutureRequest futureRequest = new FutureRequest(); new Thread(new Runnable() { @Override public void run() { SendRequest sendRequest = new SendRequest("我是請求參數"); futureRequest.sendRequest(sendRequest); } }).start(); System.out.println("主線程繼續執行"); String result = futureRequest.getResponse(); System.out.println("主線程獲得異步請求結果:" + result); } } ``` 執行結果 ``` Exception in thread "main" java.lang.NullPointerException at com.mask.FutureRequest.getResponse(FutureRequest.java:23) at com.mask.test.main(ThreadDemo.java:98) 正在讀取數據... 讀取數據完成... ``` 很顯然在獲取結果的時候報了空指針的異常,SendRequest 構造函數sleep了3秒,主線程繼續執行時FutureRequest 里的sendRequest對象還未創建成功,換種說法,主線程嘗試去獲取異步遠程請求的結果,但此時遠程請求還未得到響應,自然是獲取不得。那可如何是好呢?繼續改造代碼 改造第3步的FutureRequest類中方法,加入wait、notify方法 ``` public class FutureRequest extends BaseRequest { private SendRequest sendRequest; // notify和wait 方法必須在 synchronized 中使用 public synchronized void sendRequest(SendRequest sendRequest) { this.sendRequest = sendRequest; notify(); } @Override public synchronized String getResponse() { // 如果請求還沒響應時,主線程嘗試獲取結果會一直處于等待的狀態, // 直到請求成功響應發送notify通知,等待才會解除 while (sendRequest == null) { ... wait(); ... } return sendRequest.getResponse(); } } ``` 運行結果 ``` 主線程繼續執行 異步任務正在讀取數據... 異步任務讀取數據完成... 主線程獲得異步請求結果:hello ``` 執行結果正是我們預期的結果,測試代碼中主線程創建了線程去執行異步任務,但似乎代碼看起來并不是那么的優雅,理想的future客戶端應該是包含異步和獲取異步結果,所以我們繼續優化代碼再封裝一個future客戶端供主線程使用。 ``` // Future客戶端 public class FutureClient { public BaseRequest sendRequest(String params) { FutureRequest futureRequest = new FutureRequest(); new Thread(new Runnable() { @Override public void run() { SendRequest sendRequest = new SendRequest(params); futureRequest.sendRequest(sendRequest); } }).start(); return futureRequest; } } ``` 測試 ``` class test { public static void main(String[] args) { FutureClient futureClient = new FutureClient(); BaseRequest baseRequest = futureClient.sendRequest("我是請求參數"); System.out.println("主線程繼續執行"); String result = baseRequest.getResponse(); System.out.println("主線程獲得異步請求結果:" + result); } } ``` 執行結果 ``` 主線程繼續執行 異步任務正在讀取數據... 異步任務讀取數據完成... 主線程獲得異步請求結果:hello ``` 完美
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看