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

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ### 基本用法 這是一個帶有靜態方法**work()**的類,它對該類的對象執行某些工作: ```java // concurrent/Machina.java import onjava.Nap; public class Machina { public enum State { START, ONE, TWO, THREE, END; State step() { if(equals(END)) return END; return values()[ordinal() + 1]; } } private State state = State.START; private final int id; public Machina(int id) { this.id = id; } public static Machina work(Machina m) { if(!m.state.equals(State.END)){ new Nap(0.1); m.state = m.state.step(); } System.out.println(m); return m; } @Override public String toString() { return"Machina" + id + ": " + (state.equals(State.END)? "complete" : state); } } ``` 這是一個有限狀態機,一個微不足道的機器,因為它沒有分支......它只是從頭到尾遍歷一條路徑。**work()**方法將機器從一個狀態移動到下一個狀態,并且需要100毫秒才能完成“工作”。 **CompletableFuture**可以被用來做的一件事是, 使用**completedFuture()**將它感興趣的對象進行包裝。 ```java // concurrent/CompletedMachina.java import java.util.concurrent.*; public class CompletedMachina { public static void main(String[] args) { CompletableFuture<Machina> cf = CompletableFuture.completedFuture( new Machina(0)); try { Machina m = cf.get(); // Doesn't block } catch(InterruptedException | ExecutionException e) { throw new RuntimeException(e); } } } ``` **completedFuture()**創建一個“已經完成”的**CompletableFuture**。對這樣一個未來做的唯一有用的事情是**get()**里面的對象,所以這看起來似乎沒有用。注意**CompletableFuture**被輸入到它包含的對象。這個很重要。 通常,**get()**在等待結果時阻塞調用線程。此塊可以通過**InterruptedException**或**ExecutionException**中斷。在這種情況下,阻止永遠不會發生,因為CompletableFutureis已經完成,所以答案立即可用。 當我們將**handle()**包裝在**CompletableFuture**中時,發現我們可以在**CompletableFuture**上添加操作來處理所包含的對象,使得事情變得更加有趣: ```java // concurrent/CompletableApply.java import java.util.concurrent.*; public class CompletableApply { public static void main(String[] args) { CompletableFuture<Machina> cf = CompletableFuture.completedFuture( new Machina(0)); CompletableFuture<Machina> cf2 = cf.thenApply(Machina::work); CompletableFuture<Machina> cf3 = cf2.thenApply(Machina::work); CompletableFuture<Machina> cf4 = cf3.thenApply(Machina::work); CompletableFuture<Machina> cf5 = cf4.thenApply(Machina::work); } } ``` **輸出結果**: ``` Machina0: ONE Machina0: TWO Machina0: THREE Machina0: complete ``` `thenApply()` 應用一個接收輸入并產生輸出的函數。在本例中,`work()` 函數產生的類型與它所接收的類型相同 (`Machina`),因此每個 `CompletableFuture`添加的操作的返回類型都為 `Machina`,但是(類似于流中的 `map()` )函數也可以返回不同的類型,這將體現在返回類型上。 你可以在此處看到有關**CompletableFutures**的重要信息:它們會在你執行操作時自動解包并重新包裝它們所攜帶的對象。這使得編寫和理解代碼變得更加簡單, 而不會在陷入在麻煩的細節中。 我們可以消除中間變量并將操作鏈接在一起,就像我們使用Streams一樣: ```java // concurrent/CompletableApplyChained.javaimport java.util.concurrent.*; import onjava.Timer; public class CompletableApplyChained { public static void main(String[] args) { Timer timer = new Timer(); CompletableFuture<Machina> cf = CompletableFuture.completedFuture( new Machina(0)) .thenApply(Machina::work) .thenApply(Machina::work) .thenApply(Machina::work) .thenApply(Machina::work); System.out.println(timer.duration()); } } ``` 輸出結果: ``` Machina0: ONE Machina0: TWO Machina0: THREE Machina0: complete 514 ``` 這里我們還添加了一個 `Timer`,它的功能在每一步都顯性地增加 100ms 等待時間之外,還將 `CompletableFuture` 內部 `thenApply` 帶來的額外開銷給體現出來了。 **CompletableFutures** 的一個重要好處是它們鼓勵使用私有子類原則(不共享任何東西)。默認情況下,使用 **thenApply()** 來應用一個不對外通信的函數 - 它只需要一個參數并返回一個結果。這是函數式編程的基礎,并且它在并發特性方面非常有效[^5]。并行流和 `ComplempleFutures` 旨在支持這些原則。只要你不決定共享數據(共享非常容易導致意外發生)你就可以編寫出相對安全的并發程序。 回調 `thenApply()` 一旦開始一個操作,在完成所有任務之前,不會完成 **CompletableFuture** 的構建。雖然這有時很有用,但是開始所有任務通常更有價值,這樣就可以運行繼續前進并執行其他操作。我們可通過`thenApplyAsync()` 來實現此目的: ```java // concurrent/CompletableApplyAsync.java import java.util.concurrent.*; import onjava.*; public class CompletableApplyAsync { public static void main(String[] args) { Timer timer = new Timer(); CompletableFuture<Machina> cf = CompletableFuture.completedFuture( new Machina(0)) .thenApplyAsync(Machina::work) .thenApplyAsync(Machina::work) .thenApplyAsync(Machina::work) .thenApplyAsync(Machina::work); System.out.println(timer.duration()); System.out.println(cf.join()); System.out.println(timer.duration()); } } ``` 輸出結果: ``` 116 Machina0: ONE Machina0: TWO Machina0:THREE Machina0: complete Machina0: complete 552 ``` 同步調用(我們通常使用的那種)意味著:“當你完成工作時,才返回”,而異步調用以意味著: “立刻返回并繼續后續工作”。 正如你所看到的,`cf` 的創建現在發生的更快。每次調用 `thenApplyAsync()` 都會立刻返回,因此可以進行下一次調用,整個調用鏈路完成速度比以前快得多。 事實上,如果沒有回調 `cf.join()` 方法,程序會在完成其工作之前退出。而 `cf.join()` 直到cf操作完成之前,阻止 `main()` 進程結束。我們還可以看出本示例大部分時間消耗在 `cf.join()` 這。 這種“立即返回”的異步能力需要 `CompletableFuture` 庫進行一些秘密(`client` 無感)工作。特別是,它將你需要的操作鏈存儲為一組回調。當操作的第一個鏈路(后臺操作)完成并返回時,第二個鏈路(后臺操作)必須獲取生成的 `Machina` 并開始工作,以此類推! 但這種異步機制沒有我們可以通過程序調用棧控制的普通函數調用序列,它的調用鏈路順序會丟失,因此它使用一個函數地址來存儲的回調來解決這個問題。 幸運的是,這就是你需要了解的有關回調的全部信息。程序員將這種人為制造的混亂稱為 callback hell(回調地獄)。通過異步調用,`CompletableFuture` 幫你管理所有回調。 除非你知道系統的一些具體的變化,否則你更想使用異步調用來實現程序。 - 其他操作 當你查看`CompletableFuture`的 `Javadoc` 時,你會看到它有很多方法,但這個方法的大部分來自不同操作的變體。例如,有 `thenApply()`,`thenApplyAsync()` 和第二種形式的 `thenApplyAsync()`,它們使用 `Executor` 來運行任務(在本書中,我們忽略了 `Executor` 選項)。 下面的示例展示了所有"基本"操作,這些操作既不涉及組合兩個 `CompletableFuture`,也不涉及異常(我們將在后面介紹)。首先,為了提供簡潔性和方便性,我們應該重用以下兩個實用程序: ```java package onjava; import java.util.concurrent.*; public class CompletableUtilities { // Get and show value stored in a CF: public static void showr(CompletableFuture<?> c) { try { System.out.println(c.get()); } catch(InterruptedException | ExecutionException e) { throw new RuntimeException(e); } } // For CF operations that have no value: public static void voidr(CompletableFuture<Void> c) { try { c.get(); // Returns void } catch(InterruptedException | ExecutionException e) { throw new RuntimeException(e); } } } ``` `showr()` 在 `CompletableFuture<Integer>` 上調用 `get()`,并顯示結果,`try/catch` 兩個可能會出現的異常。 `voidr()` 是 `CompletableFuture<Void>` 的 `showr()` 版本,也就是說,`CompletableFutures` 只為任務完成或失敗時顯示信息。 為簡單起見,下面的 `CompletableFutures` 只包裝整數。`cfi()` 是一個便利的方法,它把一個整數包裝在一個完整的 `CompletableFuture<Integer>` : ```java // concurrent/CompletableOperations.java import java.util.concurrent.*; import static onjava.CompletableUtilities.*; public class CompletableOperations { static CompletableFuture<Integer> cfi(int i) { return CompletableFuture.completedFuture( Integer.valueOf(i)); } public static void main(String[] args) { showr(cfi(1)); // Basic test voidr(cfi(2).runAsync(() -> System.out.println("runAsync"))); voidr(cfi(3).thenRunAsync(() -> System.out.println("thenRunAsync"))); voidr(CompletableFuture.runAsync(() -> System.out.println("runAsync is static"))); showr(CompletableFuture.supplyAsync(() -> 99)); voidr(cfi(4).thenAcceptAsync(i -> System.out.println("thenAcceptAsync: " + i))); showr(cfi(5).thenApplyAsync(i -> i + 42)); showr(cfi(6).thenComposeAsync(i -> cfi(i + 99))); CompletableFuture<Integer> c = cfi(7); c.obtrudeValue(111); showr(c); showr(cfi(8).toCompletableFuture()); c = new CompletableFuture<>(); c.complete(9); showr(c); c = new CompletableFuture<>(); c.cancel(true); System.out.println("cancelled: " + c.isCancelled()); System.out.println("completed exceptionally: " + c.isCompletedExceptionally()); System.out.println("done: " + c.isDone()); System.out.println(c); c = new CompletableFuture<>(); System.out.println(c.getNow(777)); c = new CompletableFuture<>(); c.thenApplyAsync(i -> i + 42) .thenApplyAsync(i -> i * 12); System.out.println("dependents: " + c.getNumberOfDependents()); c.thenApplyAsync(i -> i / 2); System.out.println("dependents: " + c.getNumberOfDependents()); } } ``` **輸出結果** : ``` 1 runAsync thenRunAsync runAsync is static 99 thenAcceptAsync: 4 47 105 111 8 9 cancelled: true completed exceptionally: true done: true java.util.concurrent.CompletableFuture@6d311334[Complet ed exceptionally] 777 dependents: 1 dependents: 2 ``` - `main()` 包含一系列可由其 `int` 值引用的測試。 - `cfi(1)` 演示了 `showr()` 正常工作。 - `cfi(2)` 是調用 `runAsync()` 的示例。由于 `Runnable` 不產生返回值,因此使用了返回 `CompletableFuture <Void>` 的`voidr()` 方法。 - 注意使用 `cfi(3)`,`thenRunAsync()` 效果似乎與 上例 `cfi(2)` 使用的 `runAsync()`相同,差異在后續的測試中體現: - `runAsync()` 是一個 `static` 方法,所以你通常不會像`cfi(2)`一樣調用它。相反你可以在 `QuittingCompletable.java` 中使用它。 - 后續測試中表明 `supplyAsync()` 也是靜態方法,區別在于它需要一個 `Supplier` 而不是`Runnable`, 并產生一個`CompletableFuture<Integer>` 而不是 `CompletableFuture<Void>`。 - `then` 系列方法將對現有的 `CompletableFuture<Integer>` 進一步操作。 - 與 `thenRunAsync()` 不同,`cfi(4)`,`cfi(5)` 和`cfi(6)` "then" 方法的參數是未包裝的 `Integer`。 - 通過使用 `voidr()`方法可以看到: - `AcceptAsync()`接收了一個 `Consumer`,因此不會產生結果。 - `thenApplyAsync()` 接收一個`Function`, 并生成一個結果(該結果的類型可以不同于其輸入類型)。 - `thenComposeAsync()` 與 `thenApplyAsync()`非常相似,唯一區別在于其 `Function` 必須產生已經包裝在`CompletableFuture`中的結果。 - `cfi(7)` 示例演示了 `obtrudeValue()`,它強制將值作為結果。 - `cfi(8)` 使用 `toCompletableFuture()` 從 `CompletionStage` 生成一個`CompletableFuture`。 - `c.complete(9)` 顯示了如何通過給它一個結果來完成一個`task`(`future`)(與 `obtrudeValue()` 相對,后者可能會迫使其結果替換該結果)。 - 如果你調用 `CompletableFuture`中的 `cancel()`方法,如果已經完成此任務,則正常結束。 如果尚未完成,則使用 `CancellationException` 完成此 `CompletableFuture`。 - 如果任務(`future`)完成,則**getNow()**方法返回`CompletableFuture`的完成值,否則返回`getNow()`的替換參數。 - 最后,我們看一下依賴(`dependents`)的概念。如果我們將兩個`thenApplyAsync()`調用鏈路到`CompletableFuture`上,則依賴項的數量不會增加,保持為1。但是,如果我們另外將另一個`thenApplyAsync()`直接附加到`c`,則現在有兩個依賴項:兩個一起的鏈路和另一個單獨附加的鏈路。 - 這表明你可以使用一個`CompletionStage`,當它完成時,可以根據其結果派生多個新任務。
                  <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>

                              哎呀哎呀视频在线观看