<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 1\. 環境準備 在`Spring Boot`入口類上配置`@EnableAsync`注解開啟異步處理。 ![](https://img.kancloud.cn/75/cb/75cb7954f657557d7c2e7ab2cf50e708_936x250.png) 創建任務抽象類`AbstractTask`,并分別配置三個任務方法`doTaskOne()`,`doTaskTwo()`,`doTaskThree()`。 ![](https://img.kancloud.cn/4f/a0/4fa0d1adcc03eb2386722f63709b8963_469x191.png) ~~~ public abstract class AbstractTask { private static Random random = new Random(); public void doTaskOne() throws Exception { System.out.println("開始做任務一"); long start = currentTimeMillis(); sleep(random.nextInt(10000)); long end = currentTimeMillis(); System.out.println("完成任務一,耗時:" + (end - start) + "毫秒"); } public void doTaskTwo() throws Exception { System.out.println("開始做任務二"); long start = currentTimeMillis(); sleep(random.nextInt(10000)); long end = currentTimeMillis(); System.out.println("完成任務二,耗時:" + (end - start) + "毫秒"); } public void doTaskThree() throws Exception { System.out.println("開始做任務三"); long start = currentTimeMillis(); sleep(random.nextInt(10000)); long end = currentTimeMillis(); System.out.println("完成任務三,耗時:" + (end - start) + "毫秒"); } } ~~~ ## 2\. 同步調用 下面通過一個簡單示例來直觀的理解什么是同步調用: * 定義`Task`類,繼承`AbstractTask`,三個處理函數分別模擬三個執行任務的操作,操作消耗時間隨機取(`10`秒內)。 * ![](https://img.kancloud.cn/77/fe/77fe76d52a910585ec2d0ceb06504288_379x131.png) ~~~ @Component public class SyncTask extends AbstractTask { } ~~~ * 在**單元測試**用例中,注入`SyncTask`對象,并在測試用例中執行`doTaskOne()`,`doTaskTwo()`,`doTaskThree()`三個方法。 ![](https://img.kancloud.cn/18/5c/185c428afb4517db72af23dbfe34198f_456x304.png) ~~~ @RunWith(SpringRunner.class) @SpringBootTest public class TaskTest { @Autowired private SyncTask task; @Test public void testSyncTasks() throws Exception { task.doTaskOne(); task.doTaskTwo(); task.doTaskThree(); } } ~~~ * 執行單元測試,可以看到類似如下輸出: ~~~ 開始做任務一 完成任務一,耗時:6720毫秒 開始做任務二 完成任務二,耗時:6604毫秒 開始做任務三 完成任務三,耗時:9448毫秒 ~~~ 任務一、任務二、任務三順序的執行完了,換言之`doTaskOne()`,`doTaskTwo()`,`doTaskThree()`三個方法順序的執行完成。 ## 3\. 異步調用 上述的**同步調用**雖然順利的執行完了三個任務,但是可以看到**執行時間比較長**,若這三個任務本身之間**不存在依賴關系**,可以**并發執行**的話,同步調用在**執行效率**方面就比較差,可以考慮通過**異步調用**的方式來**并發執行**。 * 創建`AsyncTask`類,分別在方法上配置`@Async`注解,將原來的**同步方法**變為**異步方法**。 ![](https://img.kancloud.cn/b5/30/b530253da4fae7856cac85352e282451_465x233.png) ~~~ @Component public class AsyncTask extends AbstractTask { @Async public void doTaskOne() throws Exception { super.doTaskOne(); } @Async public void doTaskTwo() throws Exception { super.doTaskTwo(); } @Async public void doTaskThree() throws Exception { super.doTaskThree(); } } ~~~ * 在**單元測試**用例中,注入`AsyncTask`對象,并在測試用例中執行`doTaskOne()`,`doTaskTwo()`,`doTaskThree()`三個方法。 ~~~ @Autowired private AsyncTask asyncTask; @Test public void testAsyncTasks() throws Exception { asyncTask.doTaskOne(); asyncTask.doTaskTwo(); asyncTask.doTaskThree(); } ~~~ * 執行單元測試,可以看到類似如下輸出: ~~~ 開始做任務三 開始做任務一 開始做任務二 ~~~ 如果反復執行單元測試,可能會遇到各種不同的結果,比如: 1. 沒有任何任務相關的輸出 2. 有部分任務相關的輸出 3. 亂序的任務相關的輸出 原因是目前`doTaskOne()`,`doTaskTwo()`,`doTaskThree()`這三個方法已經**異步執行**了。主程序在**異步調用**之后,主程序并不會理會這三個函數是否執行完成了,由于沒有其他需要執行的內容,所以程序就**自動結束**了,導致了**不完整**或是**沒有輸出任務**相關內容的情況。 > 注意:@Async所修飾的函數不要定義為static類型,這樣異步調用不會生效。 ### 4\. 異步回調 為了讓`doTaskOne()`,`doTaskTwo()`,`doTaskThree()`能正常結束,假設我們需要統計一下三個任務**并發執行**共耗時多少,這就需要等到上述三個函數都完成動用之后記錄時間,并計算結果。 那么我們如何判斷上述三個**異步調用**是否已經執行完成呢?我們需要使用`Future<T>`來返回**異步調用**的**結果**。 * 創建`AsyncCallBackTask`類,聲明`doTaskOneCallback()`,`doTaskTwoCallback()`,`doTaskThreeCallback()`三個方法,對原有的三個方法進行包裝。 ![](https://img.kancloud.cn/45/7b/457b55b8b34a2d10d6092987377880a1_474x359.png) ~~~ @Component public class AsyncCallBackTask extends AbstractTask { @Async public Future<String> doTaskOneCallback() throws Exception { super.doTaskOne(); return new AsyncResult<>("任務一完成"); } @Async public Future<String> doTaskTwoCallback() throws Exception { super.doTaskTwo(); return new AsyncResult<>("任務二完成"); } @Async public Future<String> doTaskThreeCallback() throws Exception { super.doTaskThree(); return new AsyncResult<>("任務三完成"); } } ~~~ * 在**單元測試**用例中,注入`AsyncCallBackTask`對象,并在測試用例中執行`doTaskOneCallback()`,`doTaskTwoCallback()`,`doTaskThreeCallback()`三個方法。循環調用`Future`的`isDone()`方法等待三個**并發任務**執行完成,記錄最終執行時間。 ~~~ @Autowired private AsyncCallBackTask asyncCallBackTask; @Test public void testAsyncCallbackTask() throws Exception { long start = currentTimeMillis(); Future<String> task1 = asyncCallBackTask.doTaskOneCallback(); Future<String> task2 = asyncCallBackTask.doTaskTwoCallback(); Future<String> task3 = asyncCallBackTask.doTaskThreeCallback(); // 三個任務都調用完成,退出循環等待 while (!task1.isDone() || !task2.isDone() || !task3.isDone()) { sleep(1000); } long end = currentTimeMillis(); System.out.println("任務全部完成,總耗時:" + (end - start) + "毫秒"); } ~~~ 看看都做了哪些改變: * 在測試用例一開始記錄開始時間; * 在調用三個異步函數的時候,返回Future類型的結果對象; * 在調用完三個異步函數之后,開啟一個循環,根據返回的Future對象來判斷三個異步函數是否都結束了。若都結束,就結束循環;若沒有都結束,就等1秒后再判斷。 * 跳出循環之后,根據結束時間 - 開始時間,計算出三個任務并發執行的總耗時。 執行一下上述的單元測試,可以看到如下結果: ~~~ 開始做任務三 開始做任務一 開始做任務二 完成任務二,耗時:2572毫秒 完成任務一,耗時:7333毫秒 完成任務三,耗時:7647毫秒 任務全部完成,總耗時:8013毫秒 ~~~ 可以看到,通過**異步調用**,讓任務一、任務二、任務三**并發執行**,有效的**減少**了程序的**運行總時間**。
                  <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>

                              哎呀哎呀视频在线观看