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

เธรดแพลตฟอร์มเทียบกับเธรดเสมือน

เลือกใช้แต่ละแบบเมื่อใด

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

เธรดสองประเภท

ปัจจุบัน Java มีเธรดอยู่สองรูปแบบ เธรดแพลตฟอร์มเป็นตัวห่อหุ้มแบบดั้งเดิมรอบเธรดของ OS ส่วนเธรดเสมือนมีน้ำหนักเบาและจัดการโดย JVM

การรู้ว่าควรเลือกใช้แต่ละแบบเมื่อใดคือหัวใจของการเขียน Java ที่ทำงานพร้อมกันและรองรับการขยายได้

การสร้างเธรดแพลตฟอร์ม

คุณสร้างเธรดแพลตฟอร์มด้วย Thread.ofPlatform() ซึ่งเป็นคู่เทียบของ Thread.ofVirtual()

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread p = Thread.ofPlatform().name("native-worker").start(() ->
            System.out.println("Platform? " + !Thread.currentThread().isVirtual()));
        p.join();
    }
}

การเปรียบเทียบต้นทุน

เธรดแพลตฟอร์มใช้ทรัพยากรมาก:

  • จองหน่วยความจำกองซ้อนประมาณ 1 MB ต่อเธรด
  • สร้างได้ช้า
  • รองรับได้เพียงไม่กี่พันเธรด

เธรดเสมือนใช้ทรัพยากรน้อย: ใช้กองซ้อนเริ่มต้นขนาดเล็ก สร้างได้รวดเร็ว และสามารถสร้างได้หลายล้านเธรด

งานที่ผูกกับการรับส่งข้อมูล

หากงานของคุณใช้เวลาส่วนใหญ่ไปกับการรอเครือข่าย ดิสก์ หรือฐานข้อมูล เธรดเสมือนจะให้ประโยชน์อย่างมาก

ขณะที่เธรดเสมือนหนึ่งเธรดกำลังรอแบบขัดขวาง เธรดพาหะของมันจะถูกปล่อยให้ไปทำงานอื่นได้ ดังนั้นเธรดของ OS เพียงไม่กี่เธรดจึงรองรับคำขอได้หลายพันรายการ

งานที่ผูกกับการคำนวณของ CPU

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

ในกรณีนี้ กลุ่มเธรดคงที่ที่มีขนาดตามจำนวนตัวประมวลผลคือเครื่องมือที่เหมาะสม

import java.util.concurrent.*;

public class Main {
    public static void main(String[] args) throws Exception {
        int cores = Runtime.getRuntime().availableProcessors();
        try (ExecutorService cpu = Executors.newFixedThreadPool(cores)) {
            Future<Long> f = cpu.submit(() -> {
                long s = 0;
                for (long i = 0; i < 1_000_000L; i++) s += i;
                return s;
            });
            System.out.println("Cores: " + cores + ", sum: " + f.get());
        }
    }
}

การจำลองการรอแบบขัดขวาง

ส่วนย่อยนี้แสดงเธรดเสมือนจำนวนมากที่หยุดพัก (เพื่อใช้แทนการรับส่งข้อมูลแบบรอ) พร้อมกัน ลองจินตนาการว่ามีเธรดแพลตฟอร์ม 10,000 เธรดทำสิ่งเดียวกัน

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class Main {
    public static void main(String[] args) {
        AtomicInteger done = new AtomicInteger();
        try (ExecutorService exec = Executors.newVirtualThreadPerTaskExecutor()) {
            for (int i = 0; i < 10_000; i++) {
                exec.submit(() -> {
                    try { Thread.sleep(50); } catch (InterruptedException e) {}
                    done.incrementAndGet();
                });
            }
        }
        System.out.println("Finished blocking tasks: " + done.get());
    }
}

สถานะดีมอน

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

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread v = Thread.ofVirtual().unstarted(() -> {});
        Thread p = Thread.ofPlatform().unstarted(() -> {});
        System.out.println("virtual daemon: " + v.isDaemon());
        System.out.println("platform daemon: " + p.isDaemon());
    }
}

ไม่สนใจลำดับความสำคัญ

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

public class Main {
    public static void main(String[] args) {
        Thread v = Thread.ofVirtual().unstarted(() -> {});
        v.setPriority(Thread.MAX_PRIORITY);
        System.out.println("Priority is still: " + v.getPriority());
    }
}

แนวทางการตัดสินใจ

หลักง่าย ๆ ที่ใช้ได้จริง:

  • มีงานจำนวนมากที่รอการรับส่งข้อมูลหรือไม่ ใช้เธรดเสมือน
  • มีการคำนวณหนักที่ถูกจำกัดด้วย CPU หรือไม่ ใช้กลุ่มเธรดแพลตฟอร์มคงที่
  • ต้องปรับแต่งเธรดในระดับ OS เช่น ลำดับความสำคัญหรือความผูกติดกับหน่วยประมวลผลหรือไม่ ใช้เธรดแพลตฟอร์ม

ทำงานร่วมกันได้

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

ทั้งสองแบบใช้ส่วนติดต่อเดียวกับ Thread ดังนั้นการใช้งานร่วมกันจึงราบรื่น

เคล็ดลับการย้ายระบบ

เมื่อย้ายบริการที่ใช้การรับส่งข้อมูลอย่างหนัก การเปลี่ยนแปลงที่น้อยที่สุดคือการสลับตัวจัดการงาน: แทนที่กลุ่มเธรดคงที่หรือกลุ่มเธรดแบบเก็บไว้ใช้ซ้ำด้วย newVirtualThreadPerTaskExecutor()

โปรดระวังการตรึงเธรดและการใช้ ThreadLocal มากเกินไป ซึ่งจะกล่าวถึงในบทเรียนถัดไป

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

เลือกภาระงานที่เธรดเสมือนให้ประโยชน์อย่างชัดเจนที่สุด

สรุป

คุณได้เปรียบเทียบรูปแบบเธรดทั้งสองแบบแล้ว:

  • เธรดแพลตฟอร์ม: ใช้ทรัพยากรมาก ทำงานบน OS เหมาะที่สุดกับงานที่ผูกกับ CPU และการปรับแต่งระดับ OS
  • เธรดเสมือน: ใช้ทรัพยากรน้อย จัดการโดย JVM เป็นดีมอนเสมอ และเหมาะที่สุดกับการทำงานพร้อมกันที่ผูกกับการรับส่งข้อมูล
  • ทั้งสองแบบทำงานร่วมกันได้และใช้ส่วนติดต่อเดียวกัน

ถัดไป: ข้อควรระวังเรื่องการตรึงเธรดและ ThreadLocals

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

บทเรียน “เธรดแพลตฟอร์มเทียบกับเธรดเสมือน” ฟรีหรือไม่

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

คุณจะเรียนรู้อะไรในบทเรียน “เธรดแพลตฟอร์มเทียบกับเธรดเสมือน”

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

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

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

บทเรียน “เธรดแพลตฟอร์มเทียบกับเธรดเสมือน” ใช้เวลานานแค่ไหน

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

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

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

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

  1. เธรดเสมือนคืออะไร
  2. การสร้างเธรดเสมือน
  3. เธรดแพลตฟอร์มเทียบกับเธรดเสมือน
  4. ข้อควรระวัง: การตรึงและ ThreadLocals
← กลับไปที่ Java Academy