ในบทความนี้ ผมจะพูดถึงวิธีที่เราสามารถสั่งซื้อเธรดต่างๆ เพื่อให้ทำงานตามลำดับที่เราต้องการ แน่นอนว่ามีวิธีดั้งเดิมในการรับประกันความเป็นระเบียบ แต่ฉันอยากจะแสดงให้คุณเห็นวิธีที่สวยงามที่เรียกว่า CompletableFuture ซึ่งถูกนำมาใช้ใน Java 8
1- CompletableFuture คืออะไร
CompletableFuture เป็นวิธีใหม่ในการรันเธรดที่ใช้งานง่ายอย่างที่คุณเห็นในตอนนี้ มาดูกันว่าเราจะรันเธรดด้วยสิ่งนี้ได้อย่างไร ขั้นแรก เราสร้างคลาส Runnable
public class TextDownloader implements Runnable { @Override public void run() { // Download text from server System.out.println("I am downloading the file containing text to a directory"); try { Thread.sleep(2000); // for simulating download wait time } catch (InterruptedException e) { e.printStackTrace(); } } }
ใน TextDownloader
class ฉันกำลังจำลองการดาวน์โหลดซึ่งต้องใช้เวลาพอสมควรจึงจะเสร็จสมบูรณ์ แน่นอนว่าเราต้องการเรียกใช้การดำเนินการดาวน์โหลดแยกกันดังนี้
CompletableFuture .runAsync(new TextDownloader());
ดูสิว่ามันง่ายและดูดีแค่ไหน! ตอนนี้เรามาเพิ่มส่วนอื่นเข้าไปแล้วประมวลผลข้อความที่ดาวน์โหลด เมื่อเราดาวน์โหลดข้อความเสร็จแล้ว (เป็นไฟล์) เราจะบันทึกข้อความนั้นไว้ในตำแหน่งใดตำแหน่งหนึ่งในระบบไฟล์ของเราเพื่อดำเนินการในภายหลัง นี่คือส่วนสำคัญ เราต้องแน่ใจว่าขั้นตอนการดาวน์โหลดเสร็จสมบูรณ์ เพื่อให้เราสามารถเข้าถึงได้ในภายหลังเพื่อดำเนินการ นี่คือคลาสโปรเซสเซอร์
public class TextProcessor implements Runnable { @Override public void run() { // Process downloaded text System.out.println("I am taking the text from the location and processing the text"); } }
และเรากำลังดำเนินการดังต่อไปนี้เพื่อให้แน่ใจว่ามีการสั่งซื้อ
CompletableFuture .runAsync(new TextDownloader()) .thenRunAsync(new TextProcessor());
วิธีการ thenRunAsyncช่วยให้แน่ใจว่าเธรดที่ดำเนินการผ่าน runAsync เสร็จสมบูรณ์ จากนั้นจึงเรียกใช้สิ่งที่ได้รับ ในตัวอย่างข้างต้น เราถือว่าเธรดที่สองรู้อยู่แล้วว่า เธรด แรกวางไฟล์ที่ดาวน์โหลดไว้ในระบบไฟล์ แต่ถ้าไม่เป็นเช่นนั้นล่ะ? มาดูกันว่าซัพพลายเออร์จะจัดการอย่างไร
public class TextDownloader2 implements Supplier<String> { @Override public String get() { System.out.println("I am downloading the file containing text to a directory"); try { Thread.sleep(2000); // for simulating download wait time } catch (InterruptedException e) { e.printStackTrace(); } return "pathToDownloadedFile"; } }
ด้านบน คุณจะเห็นโปรแกรมดาวน์โหลดข้อความเวอร์ชันปรับปรุงใหม่ ข้อแตกต่างก็คือตอนนี้ใช้อินเทอร์เฟซของซัพพลายเออร์ซึ่งเมธอด get ส่งกลับค่า เราสามารถส่งค่าที่ส่งคืนไปยังคลาสโปรเซสเซอร์เพื่อให้รู้ว่าจะหาไฟล์ที่ดาวน์โหลดได้ที่ไหน คลาสตัวประมวลผลข้อความที่ต่ออายุกำลังใช้อินเทอร์เฟซผู้บริโภคเพื่อใช้เอาต์พุตที่ซัพพลายเออร์จัดเตรียมให้
public class TextProcessor2 implements Consumer<String> { @Override public void accept(String s) { // Process downloaded text System.out.println("I am taking the text from the location and processing the text"); System.out.println("Path: " + s); } }
และเราจะใช้มันร่วมกันได้อย่างไร
CompletableFuture .supplyAsync(new TextDownloader2()) .thenAccept(new TextProcessor2());
คุณยังสามารถระบุตรรกะของคุณได้โดยตรงภายใน thenAccept ดังนี้
CompletableFuture .supplyAsync(new TextDownloader2()) .thenAccept(path -> { // some logic });
มีวิธีการต่างๆ ในคลาส CompletableFuture ที่คุณสามารถใช้ได้ เช่น thenAcceptAsync หรือ thenApplyแต่ฉันไม่ต้องการทำให้บทความยาวขึ้นในตอนนี้
ในบทช่วยสอนนี้ ฉันพูดคุยเกี่ยวกับการเรียงลำดับการประมวลผลเธรด ฉันหวังว่าคุณจะสนุกกับมัน.