0Pricing
Java Academy · บทเรียน

การจัดการข้อผิดพลาดและการยกเลิก

ส่งต่อความล้มเหลวอย่างเป็นระเบียบ

การจัดการข้อผิดพลาดและการยกเลิก เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

ความล้มเหลวในต้นไม้งาน

เมื่องานย่อยทำงานพร้อมกัน ข้อผิดพลาดอาจเกิดขึ้นในสาขาใดก็ได้ การทำงานพร้อมกันแบบมีโครงสร้างมอบวิธีที่เป็นระบบในการ ส่งต่อความล้มเหลวเหล่านั้นขึ้นไปยังงานแม่

บทเรียนนี้ครอบคลุมข้อยกเว้น การยกเลิก การขัดจังหวะ และการหมดเวลา

ข้อยกเว้นปรากฏที่ใด

งานย่อยที่โยนข้อยกเว้นจะไม่ทำให้โปรแกรมของคุณหยุดทำงานทันที ข้อยกเว้นจะถูกเก็บไว้ในตัวจัดการ Subtask ของงานนั้น ตำแหน่งที่ข้อยกเว้นปรากฏขึ้นจะขึ้นอยู่กับนโยบาย:

  • ShutdownOnFailure: ที่ throwIfFailed()
  • ShutdownOnSuccess: ที่ result() หากไม่มีงานใดสำเร็จ

การส่งต่อด้วย throwIfFailed

ในที่นี้ งานย่อยงานหนึ่งล้มเหลว throwIfFailed() จะโยนข้อยกเว้นนั้นกลับมาโดยห่อไว้ใน ExecutionException ซึ่งเราดักจับไว้ใน main

import java.util.concurrent.*;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            scope.fork(() -> "ok");
            scope.fork(() -> { throw new RuntimeException("boom"); });
            scope.join();
            scope.throwIfFailed();
            System.out.println("never reached");
        } catch (ExecutionException e) {
            System.out.println("Caught cause: " + e.getCause().getMessage());
        }
    }
}

การแปลงเป็นข้อยกเว้นที่กำหนดเอง

throwIfFailed รับฟังก์ชันเพื่อห่อสาเหตุไว้ในชนิดข้อยกเว้นของคุณเอง ทำให้ส่วนติดต่อโปรแกรมประยุกต์ของคุณสะอาดและชัดเจน

import java.util.concurrent.StructuredTaskScope;

class DataAccessException extends Exception {
    DataAccessException(Throwable cause) { super(cause); }
}

public class Main {
    public static void main(String[] args) throws Exception {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            scope.fork(() -> { throw new RuntimeException("db down"); });
            scope.join();
            scope.throwIfFailed(DataAccessException::new);
        } catch (DataAccessException e) {
            System.out.println("Wrapped: " + e.getCause().getMessage());
        }
    }
}

การยกเลิกโดยอัตโนมัติ

เมื่องานย่อยงานหนึ่งล้มเหลวภายใต้ ShutdownOnFailure scope จะ ยกเลิกงานที่อยู่ระดับเดียวกันด้วยการขัดจังหวะเธรดของงานเหล่านั้น คุณไม่ต้องเขียนโค้ดสำหรับการยกเลิกเอง

วิธีนี้ป้องกันการทำงานที่สูญเปล่าและงานที่ค้างอยู่

การขัดจังหวะคือกลไก

การยกเลิกทำงานโดย ขัดจังหวะเธรดเสมือนของงานย่อย โค้ดที่ทำงานร่วมกับกลไกนี้ควร:

  • ปล่อยให้การเรียกที่ขัดขวางการทำงานโยน InterruptedException
  • ตรวจสอบ Thread.currentThread().isInterrupted() เป็นระยะในลูปที่ทำงานนาน

การตอบสนองต่อการขัดจังหวะ

งานนี้ตรวจสอบธงการขัดจังหวะในลูป เพื่อให้หยุดก่อนกำหนดได้เมื่อ scope หยุดทำงาน

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread t = Thread.ofVirtual().start(() -> {
            long count = 0;
            while (!Thread.currentThread().isInterrupted()) {
                count++;
                if (count == 1_000_000) break;
            }
            System.out.println("Stopped after " + count + " iterations");
        });
        t.join();
    }
}

กำหนดเวลาด้วย joinUntil

หากต้องการจำกัดเวลารวม ให้ใช้ joinUntil(Instant) หากถึงกำหนดเวลาก่อนที่งานย่อยทั้งหมดจะเสร็จ ฟังก์ชันจะโยน TimeoutException และ scope จะสั่งให้งานที่เหลือหยุดทำงาน

รูปแบบการแยกงานที่มีการป้องกันการหมดเวลา

การแยกงานพร้อมกันที่มีการป้องกันการหมดเวลาโดยทั่วไปมีลักษณะดังนี้ กำหนดเวลานี้ใช้กับงานทั้งกลุ่ม ไม่ใช่กับงานย่อยแต่ละงานแยกกัน

import java.time.*;
import java.util.concurrent.*;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            scope.fork(() -> "fast");
            scope.joinUntil(Instant.now().plus(Duration.ofSeconds(2)));
            scope.throwIfFailed();
            System.out.println("Completed within deadline");
        } catch (TimeoutException e) {
            System.out.println("Deadline exceeded");
        } catch (ExecutionException e) {
            System.out.println("A subtask failed");
        }
    }
}

ตรวจสอบอีกครั้งหลัง join เสมอ

แนวปฏิบัติคือ หลังจาก join() (หรือ joinUntil) ให้เรียก throwIfFailed() หรืออ่าน result() ก่อนเชื่อถือค่าของงานย่อยใด ๆ เสมอ การข้ามขั้นตอนนี้อาจทำให้ความล้มเหลวถูกซ่อนไว้

รับประกันการหยุดทำงานอย่างสะอาด

ไม่ว่า scope จะสิ้นสุดตามปกติ เนื่องจากความล้มเหลว หรือเนื่องจากหมดเวลา การปิดบล็อก try พร้อมการจัดการทรัพยากรจะรับรองว่าเธรดของงานย่อยทุกงานเสร็จสิ้นแล้ว จะไม่มีเธรดรั่วไหลหรืองานที่ถูกทอดทิ้ง

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทบทวนวิธีหยุดงานย่อยที่อยู่ระดับเดียวกัน

สรุปทบทวน

คุณได้เรียนรู้การจัดการข้อผิดพลาดและการยกเลิก:

  • ข้อยกเว้นจะปรากฏที่ throwIfFailed() หรือ result()
  • แปลงสาเหตุเป็นข้อยกเว้นที่กำหนดเองผ่าน throwIfFailed(mapper)
  • การยกเลิกทำงานผ่าน การขัดจังหวะเธรด จึงควรเขียนงานที่ทำงานร่วมกับกลไกนี้
  • joinUntil บังคับใช้กำหนดเวลาของทั้งกลุ่ม
  • การปิด scope จะทำความสะอาดทรัพยากรเสมอ

บทเรียนนี้จบหลักสูตรการทำงานพร้อมกันแบบมีโครงสร้างแล้ว

คำถามที่พบบ่อย

บทเรียน “การจัดการข้อผิดพลาดและการยกเลิก” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การจัดการข้อผิดพลาดและการยกเลิก” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การจัดการข้อผิดพลาดและการยกเลิก”

ส่งต่อความล้มเหลวอย่างเป็นระเบียบ คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “การจัดการข้อผิดพลาดและการยกเลิก” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. โมเดลการทำงานพร้อมกันแบบมีโครงสร้าง
  2. StructuredTaskScope
  3. การปิดเมื่อเกิดความล้มเหลวและเมื่อสำเร็จ
  4. การจัดการข้อผิดพลาดและการยกเลิก
← กลับไปที่ Java Academy