-
เธรดใน Java คืออะไร?
เธรดเป็นเส้นทางการดำเนินการที่เป็นอิสระ เป้าหมายคือการใช้ประโยชน์จากโปรเซสเซอร์หลายตัวที่มีอยู่ในเครื่อง ด้วยการใช้หลายเธรด คุณสามารถเร่งความเร็วงานที่เชื่อมโยงกับ CPU ได้ ตัวอย่างเช่น หากเธรดหนึ่งใช้เวลา 100 มิลลิวินาทีในการทำงานให้เสร็จสิ้น คุณสามารถใช้ 10 เธรดเพื่อลดงานนั้นลงเหลือ 10 มิลลิวินาที Java ให้การสนับสนุนที่ยอดเยี่ยมสำหรับมัลติเธรดในระดับภาษา และยิ่งกว่านั้นคือหนึ่งในข้อได้เปรียบที่แข็งแกร่งที่สุด
-
ความแตกต่างระหว่างเธรดและกระบวนการใน Java?
เธรดคือชุดย่อยของกระบวนการ กล่าวอีกนัยหนึ่ง กระบวนการหนึ่งสามารถมีได้หลายเธรด กระบวนการทั้งสองกำลังทำงานในพื้นที่หน่วยความจำต่างกัน แต่เธรดทั้งหมดใช้พื้นที่หน่วยความจำเดียวกัน อย่าสับสนกับหน่วยความจำสแต็ก ซึ่งจะแตกต่างกันไปในแต่ละเธรด และใช้เพื่อจัดเก็บข้อมูลในเครื่องของเธรดนั้น
-
จะสร้างเธรดได้อย่างไร?
ในระดับภาษา มีสองวิธีในการสร้างเธรด อ็อบเจ็กต์ของคลาส java.lang.Thread แสดงถึงเธรด แต่ต้องมีงานจึงจะรันได้ ซึ่งเป็นอ็อบเจ็กต์ที่ใช้อินเทอร์เฟซ java.lang.Runnable เนื่องจากคลาส Thread ใช้อินเทอร์เฟซ Runnable คุณสามารถแทนที่เมธอด run() ได้โดยรับคลาสของคุณจาก Thread หรือโดยการใช้อินเทอร์เฟซ Runnable ในนั้น
-
เมื่อใดจึงควรใช้ Runnable และเมื่อใดจึงควรใช้ Thread
นี่เป็นส่วนเพิ่มเติมจากคำถามก่อนหน้า ดังที่เราทราบ เธรดสามารถสร้างขึ้นได้โดยการสืบทอดจากคลาส Thread หรือโดยการนำอินเทอร์เฟซ Runnable ไปใช้งาน คำถามเกิดขึ้น วิธีใดดีกว่า และควรใช้วิธีใดเมื่อใด คำถามนี้ตอบได้ง่ายหากคุณรู้ว่า Java ไม่รองรับการสืบทอดหลายคลาส แต่อนุญาตให้คุณใช้หลายอินเทอร์เฟซได้ ซึ่งหมายความว่าจะดีกว่าถ้าใช้ Runnable หากคุณต้องการสืบทอดจากคลาสอื่น
-
ความแตกต่างระหว่างเมธอด start() และ run() คืออะไร?
หนึ่งในเคล็ดลับคำถามในอดีต แต่ก็ยังดีพอที่จะแยกแยะความเข้าใจแบบผิวเผินเกี่ยวกับมัลติเธรดใน Java เมธอด start() ใช้ในการเริ่มเธรดใหม่ แม้ว่า start() จะเรียกใช้เมธอด run() ภายใน แต่ก็ไม่เหมือนกับการเรียกใช้ run() หากคุณเรียกใช้เมธอด run() ตามปกติ มันจะถูกเรียกใช้บนเธรดเดียวกัน และจะไม่มีการสตาร์ทเธรดใหม่ ซึ่งเป็นสิ่งที่เกิดขึ้นเมื่อคุณเรียกใช้เมธอด start()
-
ความแตกต่างระหว่าง Runnable และ Callable?
อินเทอร์เฟซทั้งสองแสดงถึงงานที่มีวัตถุประสงค์เพื่อดำเนินการในเธรดที่แยกจากกัน Runnable มีมาตั้งแต่ JDK 1.0 และมีการเพิ่ม Callable ใน JDK 1.5 ข้อแตกต่างที่สำคัญคือเมธอด call() ของ Callable สามารถคืนค่าและส่งข้อยกเว้น ซึ่งไม่สามารถทำได้ด้วยเมธอด run() ของ Runnable Callable ส่งคืนออบเจ็กต์ Future ที่สามารถมีผลการคำนวณได้
-
ความแตกต่างระหว่าง CyclicBarrier และ CountDownLatch คืออะไร
แม้ว่าซิงโครไนเซอร์ทั้งสองจะอนุญาตให้เธรดรอซึ่งกันและกัน ความแตกต่างที่สำคัญระหว่างทั้งสองก็คือ คุณจะไม่สามารถใช้ CountDownLatch ซ้ำได้หลังจากที่ตัวนับของมันถึงศูนย์ แต่คุณสามารถใช้ CyclicBarrier ได้อีกครั้งแม้ว่าแผงกั้นจะพังก็ตาม
-
หน่วยความจำ Java รุ่นคืออะไร?
โมเดลหน่วยความจำคือชุดของกฎและแนวปฏิบัติที่อนุญาตให้โปรแกรม Java ทำงานตามที่กำหนดในหน่วยความจำ ตัวประมวลผล และสถาปัตยกรรมระบบปฏิบัติการหลายตัว นี่เป็นสิ่งสำคัญอย่างยิ่งในกรณีของเส้นใยหลายเส้น โมเดลหน่วยความจำรับประกันว่าการเปลี่ยนแปลงที่ทำโดยเธรดหนึ่งจะมองเห็นได้โดยผู้อื่น หนึ่งในนั้นคือความสัมพันธ์ที่เกิดขึ้นก่อน ความสัมพันธ์นี้กำหนดกฎหลายข้อที่อนุญาตให้โปรแกรมเมอร์คาดการณ์และกำหนดลักษณะการทำงานของโปรแกรมแบบขนาน เช่น เกิดขึ้นก่อนการค้ำประกัน:
- ทุกการกระทำในเธรดจะเกิดขึ้นก่อนทุกการกระทำในเธรดนั้นที่ตามมาตามลำดับของโปรแกรม หรือที่เรียกว่ากฎลำดับโปรแกรม
- การปลดล็อคจอภาพจะเกิดขึ้นก่อนการล็อคจอภาพเดียวกันแต่ละครั้งในภายหลัง หรือที่เรียกว่ากฎการล็อคจอภาพ
- การเขียนลงในฟิลด์ที่เปลี่ยนแปลงได้จะเกิดขึ้นก่อนที่จะอ่านฟิลด์นั้นในแต่ละครั้ง ซึ่งเป็นกฎของตัวแปรที่เปลี่ยนแปลงได้
- การเรียก Thread.start() บนเธรดเกิดขึ้นก่อนที่เธรดอื่นจะแจ้งให้ทราบว่าเธรดนั้นถูกหยุดแล้ว ไม่ว่าจะหลังจาก Thread.join() สำเร็จ หรือหาก Thread.isAlive() คืนค่าเท็จ กฎ Thread.start() .
- เธรดที่ถูกขัดจังหวะโดยเธรดอื่นเกิดขึ้นก่อนที่เธรดที่ถูกขัดจังหวะจะสังเกตเห็นการขัดจังหวะ (ไม่ว่าจะจากการโยน InterruptedException หรือจากการตรวจสอบ isInterrupted()) ซึ่งเป็นกฎการขัดจังหวะของเธรด
- จุดสิ้นสุดของ Constructor ของออบเจ็กต์เกิดขึ้นก่อนการเริ่มต้น Finalizer สำหรับออบเจ็กต์นั้น ซึ่งก็คือกฎ Finalizer
- ถ้า A เกิดขึ้นก่อน B และ B เกิดขึ้นก่อน C แล้ว A เกิดขึ้นก่อน C ซึ่งหมายความว่าเกิดขึ้นก่อนที่จะรับประกันการเปลี่ยนแปลง
-
ตัวแปรผันผวนคืออะไร?
Volatile คือตัวดัดแปลงพิเศษที่สามารถใช้ได้กับแอตทริบิวต์เท่านั้น ในโปรแกรม Java แบบขนาน การเปลี่ยนแปลงที่ทำโดยเธรดที่แตกต่างกันในแอ็ตทริบิวต์จะไม่ปรากฏให้ผู้อื่นเห็นหากไม่มีตัวซิงโครไนซ์ ตัวแปรผันผวนช่วยให้แน่ใจว่าการเขียนจะเกิดขึ้นก่อนการอ่านครั้งต่อไป ดังที่ระบุไว้ในกฎตัวแปรผันผวนในคำถามก่อนหน้า
-
ความปลอดภัยของเธรดคืออะไร? คลาส Vector ปลอดภัยหรือไม่?
ความปลอดภัยของเธรดเป็นคุณสมบัติของออบเจ็กต์หรือโค้ดที่ทำให้แน่ใจว่าเมื่อเรียกใช้งานหรือใช้งานโดยหลายเธรด โค้ดจะทำงานตามที่ตั้งใจไว้ ตัวอย่างเช่น ตัวนับเธรดที่ปลอดภัยจะไม่ข้ามการนับใดๆ หากใช้อินสแตนซ์ตัวนับเดียวกันระหว่างหลายเธรด แน่นอนว่า คลาสคอลเลกชันสามารถแบ่งออกเป็นสองประเภท คือ thread-safe และ non-thread-safe Vector ปลอดภัยสำหรับเธรดและบรรลุเป้าหมายนี้โดยการซิงโครไนซ์วิธีการเปลี่ยนสถานะของ Vector ในทางกลับกัน ArrayList ที่เทียบเท่ากันนั้นไม่ปลอดภัยสำหรับเธรด
-
สภาพการแข่งขันคืออะไร?
สภาพการแข่งขันเป็นสาเหตุของข้อบกพร่องเล็กๆ น้อยๆ ดังที่ชื่อกล่าวไว้ สภาพการแข่งขันเกิดขึ้นเนื่องจากการแข่งขันระหว่างหลายเธรด หากเธรดที่ควรดำเนินการก่อนสูญเสียการแข่งขันและเธรดที่สองถูกดำเนินการ พฤติกรรมของโค้ดจะเปลี่ยนไป ทำให้เกิดข้อบกพร่องที่ไม่สามารถกำหนดได้ เหล่านี้คือข้อบกพร่องที่ยากที่สุดในการจับและทำซ้ำเนื่องจากธรรมชาติที่ยุ่งเหยิงของการแข่งขันระหว่างเธรด ตัวอย่างของสภาวะการแข่งขันคือการดำเนินการที่ไม่แน่นอน
-
จะหยุดเธรดได้อย่างไร?
ฉันพูดอยู่เสมอว่า Java มี API ที่หลากหลายสำหรับทุกสิ่ง แต่ที่น่าขันกลับไม่ได้ให้วิธีที่สะดวกในการหยุดเธรด JDK 1.0 มีวิธีควบคุมหลายวิธี เช่น stop(), Suspend() และ Resume() ที่ถูกทำเครื่องหมายว่าเลิกใช้แล้วในรีลีสในอนาคตเนื่องจากภัยคุกคามที่อาจเกิดการชะงักงัน ตั้งแต่นั้นเป็นต้นมา นักพัฒนา Java API ก็ไม่ได้พยายามที่จะจัดเตรียมเธรด -ทนทาน -วิธีที่ปลอดภัยและสง่างามในการหยุดเธรด โปรแกรมเมอร์ส่วนใหญ่พึ่งพาความจริงที่ว่าเธรดหยุดตัวเองทันทีที่ดำเนินการเมธอด run() หรือ call() เสร็จสิ้น หากต้องการหยุดด้วยตนเอง โปรแกรมเมอร์จะใช้ประโยชน์จากตัวแปรบูลีนที่ระเหยได้ และตรวจสอบค่าของมันในการวนซ้ำแต่ละครั้งว่ามีลูปในเมธอด run() หรือไม่ หรือขัดจังหวะเธรดด้วยเมธอด Interrupt() เพื่อยกเลิกงานกะทันหัน
-
จะเกิดอะไรขึ้นเมื่อเธรดส่งข้อยกเว้น?
นี่เป็นหนึ่งในคำถามเคล็ดลับที่ดี พูดง่ายๆ ก็คือ หากตรวจไม่พบข้อยกเว้น เธรดนั้นก็จะไม่ทำงาน หากมีการติดตั้งตัวจัดการสำหรับข้อยกเว้นที่ไม่ถูกตรวจจับ เธรดนั้นก็จะได้รับการติดต่อกลับ Thread.UncaughtExceptionHandler เป็นอินเทอร์เฟซที่กำหนดให้เป็นอินเทอร์เฟซแบบซ้อนสำหรับตัวจัดการที่ถูกเรียกเมื่อเธรดหยุดกะทันหันเนื่องจากข้อยกเว้นที่ไม่ถูกตรวจจับ เมื่อเธรดกำลังจะตายเนื่องจากข้อยกเว้นที่ไม่ถูกตรวจจับ JVM จะตรวจสอบการมีอยู่ของ UncaughtExceptionHandler โดยใช้ Thread.getUncaughtExceptionHandler() และเรียกใช้เมธอด uncaughtException() ของตัวจัดการ โดยส่งผ่านเธรดและข้อยกเว้นเป็นอาร์กิวเมนต์
-
จะแชร์ข้อมูลระหว่างสองเธรดได้อย่างไร?
คุณสามารถแชร์ข้อมูลระหว่างเธรดโดยใช้อ็อบเจ็กต์ที่ใช้ร่วมกันหรือโครงสร้างข้อมูลแบบขนาน เช่น BlockingQueue
-
ความแตกต่างระหว่าง notify และ notifyAll?
นี่เป็นคำถามที่ยุ่งยากอีกข้อหนึ่ง เนื่องจากมอนิเตอร์ตัวเดียวสามารถตรวจสอบได้โดยใช้หลายเธรด นักพัฒนา Java API จึงเตรียมวิธีการแจ้งเธรดเดียวหรือทั้งหมดเกี่ยวกับการเปลี่ยนแปลงในสถานะ แต่ให้การดำเนินการเพียงครึ่งเดียวเท่านั้น เมธอด notify() ไม่มีวิธีเลือกเธรดเฉพาะ ดังนั้นจึงมีประโยชน์เฉพาะเมื่อคุณทราบแน่ชัดว่ามีเธรดเดียวเท่านั้นที่กำลังรออยู่ ในทางกลับกัน notifyAll() จะแจ้งเตือนเธรดทั้งหมดและอนุญาตให้เธรดเหล่านั้นแข่งขันกันเพื่อมอนิเตอร์ ซึ่งจะทำให้แน่ใจได้ว่าอย่างน้อยหนึ่งเธรดจะเคลื่อนไปข้างหน้า
-
เหตุใดจึงรอแจ้งเตือนและแจ้งเตือนทั้งหมดไม่อยู่ในคลาสเธรด
นี่เป็นคำถามการออกแบบที่จะทดสอบว่าผู้สมัครคิดอย่างไรเกี่ยวกับระบบที่มีอยู่ หรือว่าพวกเขาเคยคิดถึงสิ่งที่คล้ายกันซึ่งดูผิดปรกติในตอนแรกหรือไม่ เพื่อตอบคำถามนี้ คุณต้องระบุเหตุผลหลายประการว่าทำไมวิธีการเหล่านี้ถึงดีกว่าในคลาส Object และเหตุใดจึงไม่อยู่ในคลาส Thread เหตุผลแรกที่ชัดเจนคือ Java รองรับการล็อกที่ระดับอ็อบเจ็กต์ ไม่ใช่ที่ระดับเธรด วัตถุใด ๆ มีการล็อคซึ่งได้มาโดยเธรด และถ้าเธรดจำเป็นต้องรอการล็อคบางอย่าง การเรียก wait() บนอ็อบเจ็กต์จะเหมาะสมกว่าการเรียกเธรดนี้ หากมีการประกาศ wait() ในคลาส Thread จะไม่ชัดเจนว่าการล็อกใดที่เธรดกำลังรออยู่ กล่าวโดยย่อ เนื่องจากรอ แจ้งเตือน และแจ้งเตือนทั้งหมดทำงานที่ระดับล็อค จึงสะดวกกว่าในการประกาศในคลาสอ็อบเจ็กต์เนื่องจากการล็อกอ้างถึงอ็อบเจ็กต์
-
ตัวแปร ThreadLocal คืออะไร
ตัวแปร ThreadLocal เป็นตัวแปรชนิดพิเศษที่มีให้สำหรับโปรแกรมเมอร์ Java เช่นเดียวกับที่รัฐมีตัวแปรสถานะ เธรดก็มีตัวแปร ThreadLocal นี่เป็นวิธีที่ดีในการบรรลุความปลอดภัยของเธรดสำหรับวัตถุที่มีราคาแพงในการสร้าง ตัวอย่างเช่น คุณสามารถทำให้เธรด SimpleDateFormat ปลอดภัยได้โดยใช้ ThreadLocal เนื่องจากนี่เป็นคลาสที่มีราคาแพง จึงไม่แนะนำให้ใช้ในขอบเขตท้องถิ่นที่ต้องใช้อินสแตนซ์แยกต่างหากสำหรับการโทรแต่ละครั้ง ด้วยการให้แต่ละด้ายมีสำเนาของตัวเอง คุณจะฆ่านกสองตัวด้วยหินนัดเดียว ประการแรก คุณลดจำนวนอินสแตนซ์ของออบเจ็กต์ราคาแพงโดยใช้จำนวนอินสแตนซ์ใหม่คงที่ และประการที่สอง คุณจะได้รับความปลอดภัยของเธรดโดยไม่สูญเสียการซิงโครไนซ์และการเปลี่ยนแปลงไม่ได้ อีกตัวอย่างที่ดีของตัวแปรเธรดภายในเครื่องคือคลาส ThreadLocalRandom ซึ่งช่วยลดจำนวนอินสแตนซ์ของอ็อบเจ็กต์ Random ที่มีราคาแพงในการสร้างในสภาพแวดล้อมแบบมัลติเธรด
-
FutureTask คืออะไร?
FutureTask คือการคำนวณแบบอะซิงโครนัสที่ยกเลิกได้ในแอปพลิเคชัน Java แบบขนาน คลาสนี้จัดเตรียมการใช้งานในอนาคตขั้นพื้นฐาน โดยมีวิธีการสำหรับการเริ่มต้นและหยุดการคำนวณ วิธีการสอบถามสถานะของการคำนวณ และการดึงผลลัพธ์ ผลลัพธ์สามารถรับได้เมื่อการคำนวณเสร็จสิ้นเท่านั้น วิธี getter จะบล็อกหากการคำนวณยังไม่เสร็จสิ้น อ็อบเจ็กต์ FutureTask สามารถใช้เพื่อตัดอ็อบเจ็กต์ Callable และ Runnable ได้ เนื่องจาก FutureTask ใช้ Runnable จึงสามารถส่งผ่านไปยัง Executor เพื่อดำเนินการได้
-
ความแตกต่างระหว่างถูกขัดจังหวะและถูกขัดจังหวะ?
ข้อแตกต่างที่สำคัญระหว่าง Interrupted() และ isInterrupted() ก็คือ แบบแรกจะรีเซ็ตสถานะการขัดจังหวะ ในขณะที่แบบหลังไม่รีเซ็ต กลไกการขัดจังหวะใน Java ถูกนำมาใช้โดยใช้แฟล็กภายในที่เรียกว่าสถานะขัดจังหวะ การขัดจังหวะเธรดโดยการเรียก Thread.interrupt() จะตั้งค่าสถานะนี้ เมื่อเธรดที่ถูกขัดจังหวะตรวจสอบสถานะขัดจังหวะโดยการเรียกเมธอด Thread.interrupted() แบบคงที่ สถานะขัดจังหวะจะถูกรีเซ็ต เมธอด isInterrupted() แบบไม่คงที่ ซึ่งใช้โดยเธรดเพื่อตรวจสอบสถานะการขัดจังหวะของเธรดอื่น จะไม่เปลี่ยนแฟล็กขัดจังหวะ ตามธรรมเนียมแล้ว วิธีการใดๆ ที่ยุติลงด้วยการส่ง InterruptedException จะรีเซ็ตค่าสถานะขัดจังหวะ อย่างไรก็ตาม มีความเป็นไปได้เสมอที่แฟล็กจะถูกตั้งค่าอีกครั้งทันทีหากเธรดอื่นเรียก Interrupt()
-
เหตุใดวิธีการรอและแจ้งเตือนจึงถูกเรียกในบล็อกที่ซิงโครไนซ์
เหตุผลหลักในการเรียกการรอและแจ้งเตือนจากบล็อกหรือเมธอดแบบสแตติกก็คือ Java API จำเป็นต้องใช้ หากคุณเรียกพวกเขาจากภายนอกบล็อกที่ซิงโครไนซ์ รหัสของคุณจะส่ง IllegalMonitorStateException เหตุผลที่ฉลาดกว่าคือการหลีกเลี่ยงสภาวะการแข่งขันระหว่างการรอและการแจ้งสาย
-
เหตุใดคุณจึงควรตรวจสอบสถานะการรอแบบวนซ้ำ
มีความเป็นไปได้ที่เธรดที่รอจะได้รับคำเตือนที่ผิดพลาดและการเรียกปลุกที่ผิดพลาด หากไม่ได้ตรวจสอบสถานะการรอในลูป เธรดก็จะออกแม้ว่าจะไม่ถึงสถานะก็ตาม เมื่อเธรดที่กำลังรอกลับมาทำงาน เธรดนั้นไม่ได้คำนึงถึงข้อเท็จจริงที่ว่าสถานะที่เธรดกำลังรอนั้นอาจยังคงมีผลอยู่ จริงๆ แล้วอาจเป็นอดีตก็ได้ แต่หลังจากนั้นก็เปลี่ยนไปหลังจากเรียกใช้เมธอด notify() และก่อนที่เธรดจะเริ่มทำงาน ดังนั้นจึงเป็นการดีกว่าเสมอที่จะเรียก wait() จากภายในลูป
-
ความแตกต่างระหว่างคอลเลกชันที่ซิงโครไนซ์และพร้อมกัน?
แม้ว่าคอลเลกชั่นทั้งแบบซิงโครไนซ์และพร้อมกันจะให้คอลเลกชั่นที่ปลอดภัยสำหรับเธรด แต่คอลเลกชั่นหลังสามารถปรับขนาดได้มากกว่า ก่อน Java 1.5 โปรแกรมเมอร์จะเข้าถึงได้เฉพาะคอลเลกชันที่ซิงโครไนซ์เท่านั้น ซึ่งกลายเป็นที่มาของการโต้แย้งเมื่อมีเธรดหลายตัวเข้าถึงพร้อมกัน ทำให้ยากต่อการปรับขนาดระบบ Java 5 เปิดตัวคอลเลกชันที่เกิดขึ้นพร้อมกัน เช่น ConcurrentHashMap ซึ่งไม่เพียงแต่ให้ความปลอดภัยของเธรด แต่ยังปรับปรุงความสามารถในการขยายขนาดโดยใช้เทคนิคสมัยใหม่ เช่น การลอกแบบล็อค และการแบ่งพาร์ติชันตารางภายใน
-
ความแตกต่างระหว่างสแต็คและฮีป?
เหตุใดคำถามนี้จึงปรากฏในคำถามเกี่ยวกับมัลติเธรด เนื่องจากสแต็กเป็นส่วนของหน่วยความจำที่สัมพันธ์กับเธรดอย่างใกล้ชิด แต่ละเธรดมีสแต็กของตัวเอง ซึ่งจัดเก็บตัวแปรในเครื่อง พารามิเตอร์เมธอด และสแต็กการเรียก ตัวแปรที่เก็บไว้ในสแต็กของเธรดหนึ่งจะไม่สามารถมองเห็นได้จากอีกเธรดหนึ่ง ในทางกลับกันฮีปเป็นพื้นที่หน่วยความจำทั่วไปที่แชร์ระหว่างเธรดทั้งหมด ออบเจ็กต์ไม่ว่าจะเป็นระดับท้องถิ่นหรือระดับอื่นจะถูกสร้างขึ้นบนฮีป เพื่อปรับปรุงประสิทธิภาพ เธรดมักจะแคชค่าจากฮีปไปยังสแต็ก ซึ่งเป็นจุดที่ตัวแปรระเหยเข้ามามีบทบาท Volatile บอกให้เธรดอ่านตัวแปรจากหน่วยความจำหลัก
-
เธรดพูลคืออะไร?
การสร้างเธรดมีราคาแพงในแง่ของเวลาและทรัพยากร หากคุณสร้างเธรดในขณะที่คำขอกำลังประมวลผล จะทำให้เวลาตอบสนองช้าลง และกระบวนการสามารถสร้างเธรดได้ในจำนวนที่จำกัดเท่านั้น เพื่อหลีกเลี่ยงปัญหาเหล่านี้ กลุ่มของเธรดจะถูกสร้างขึ้นเมื่อเริ่มต้นแอปพลิเคชัน และเธรดจะถูกนำมาใช้ซ้ำในการประมวลผลคำขอ กลุ่มเธรดนี้เรียกว่า "กลุ่มเธรด" และเธรดในนั้นเรียกว่าเธรดผู้ปฏิบัติงาน เริ่มต้นด้วย Java 1.5 Java API จัดเตรียมเฟรมเวิร์ก Executor ซึ่งช่วยให้คุณสามารถสร้างเธรดพูลต่างๆ ได้ เช่น เธรดพูลเดี่ยวซึ่งประมวลผลเพียงหนึ่งงานต่อหน่วยเวลา เธรดพูลคงที่ พูลที่มีหมายเลขคงที่ ของเธรด และเธรดพูลที่แคชไว้ ซึ่งเป็นพูลที่ขยายได้ เหมาะสำหรับแอปพลิเคชันที่มีงานระยะสั้นจำนวนมาก
-
จะแก้ไขปัญหาผู้บริโภคของผู้ผลิตได้อย่างไร?
ปัญหาเธรดส่วนใหญ่ที่คุณแก้ไขในความเป็นจริงมาจากรูปแบบ Producer Consumer โดยที่หนึ่งเธรดจะสร้างปัญหา และเธรดที่สองใช้มัน คุณจำเป็นต้องทราบวิธีสร้างการโต้ตอบของเธรดภายในเพื่อแก้ไขปัญหานี้ ในระดับต่ำ คุณสามารถใช้ประโยชน์จากวิธีการรอและแจ้งเตือน และในระดับสูง คุณสามารถใช้ประโยชน์จาก Semaphore หรือ BlockingQueue
-
จะหลีกเลี่ยงการหยุดชะงักได้อย่างไร?
การหยุดชะงักเป็นสถานะที่เธรดกำลังรอให้เธรดที่สองดำเนินการบางอย่าง และเธรดที่สองในเวลาเดียวกันก็กำลังรอเหมือนกันจากครั้งแรก นี่เป็นปัญหาร้ายแรงมากที่ทำให้โปรแกรมของคุณหยุดทำงานและไม่ทำตามที่ออกแบบไว้ การหยุดชะงักเกิดขึ้นเมื่อถึง 4 สถานะเหล่านี้:
- การยกเว้นร่วมกัน:ต้องมีทรัพยากรอย่างน้อยหนึ่งรายการในโหมดแบ่งแยกไม่ได้ มีเพียงกระบวนการเดียวเท่านั้นที่สามารถใช้ทรัพยากรในเวลาที่กำหนดได้
- พักและรอ:กระบวนการเก็บทรัพยากรอย่างน้อยหนึ่งรายการและร้องขอทรัพยากรเพิ่มเติมที่กระบวนการอื่นถือไว้
- ไม่มีการล้างข้อมูลล่วงหน้า:ระบบปฏิบัติการจะไม่มอบหมายทรัพยากรใหม่หากทรัพยากรถูกครอบครองแล้ว จะต้องมอบให้กับกระบวนการระงับโดยสมัครใจ
- การรอแบบวนรอบ:กระบวนการรอให้ทรัพยากรถูกปล่อยออกมาโดยกระบวนการอื่น ซึ่งจะรอให้ทรัพยากรถูกปล่อยออกมาโดยกระบวนการแรก
-
ความแตกต่างระหว่าง livelock และ deadlock?
livelock นั้นคล้ายคลึงกับการ deadlock เฉพาะใน livelock เท่านั้นที่สถานะของเธรดหรือกระบวนการที่เกี่ยวข้องจะเปลี่ยนแปลงอยู่ตลอดเวลาโดยขึ้นอยู่กับกันและกัน Livelock เป็นกรณีพิเศษของการขาดแคลนทรัพยากร ตัวอย่างที่แท้จริงของการอยู่ร่วมกันคือเมื่อคนสองคนพบกันในทางเดินแคบๆ และแต่ละคนพยายามที่จะแสดงตัวสุภาพและก้าวออกไป และพวกเขาก็เคลื่อนตัวจากด้านหนึ่งไปอีกด้านหนึ่งอย่างไม่สิ้นสุด
การแปล: คำถามสัมภาษณ์ 50 อันดับแรกเรียงตามกระทู้ ส่วนที่ 1.
ส่วนแรกของการแปลบทความต้นฉบับคำตอบสำหรับคำถามสัมภาษณ์กระทู้ Java 50 อันดับแรกสำหรับนักศึกษาใหม่ โปรแกรมเมอร์ที่มีประสบการณ์
ส่วนที่สอง.
หมายเหตุ:บทความนี้มีขนาดใหญ่ จึงไม่เหมาะกับหัวข้อเดียว นอกจากนี้ มันค่อนข้างซับซ้อน ฉันพยายามอย่างเต็มที่ที่จะหามันใน Google แต่ถึงกระนั้น ดังนั้นเราจึงขอให้ผู้เข้าร่วมที่พูดภาษาอังกฤษได้คล่องดูต้นฉบับและเปรียบเทียบกับการแปล เผื่อในกรณีที่พวกเขาเข้าใจผิดหรือแปลไม่ถูกต้อง ขอบคุณล่วงหน้า. ในการสัมภาษณ์ ไม่ว่าจะเป็นรุ่นอาวุโสหรือรุ่นน้อง ผู้มีประสบการณ์หรือมือใหม่ คุณจะต้องเผชิญกับคำถามสองสามข้อเกี่ยวกับ threads ความเท่าเทียม และ multi-threading ในความเป็นจริง การสนับสนุนการทำงานพร้อมกันในตัวนี้เป็นหนึ่งในจุดแข็งที่ยิ่งใหญ่ที่สุดของ Java และช่วยให้ได้รับความนิยมในหมู่ผู้ประกอบการและโปรแกรมเมอร์ ตำแหน่งนักพัฒนา Java ที่ร่ำรวยส่วนใหญ่ต้องการทักษะแบบมัลติเธรดที่ยอดเยี่ยมและประสบการณ์ในการพัฒนา การดีบัก และการปรับแต่งแอปพลิเคชันประสิทธิภาพสูงและมีเวลาแฝงต่ำ ดังนั้นจึงเป็นหนึ่งในทักษะที่เป็นที่ต้องการมากที่สุดในการสัมภาษณ์ ในการสัมภาษณ์ Java ทั่วไป ผู้สัมภาษณ์จะค่อยๆ เริ่มต้นด้วยแนวคิดพื้นฐานของเธรด โดยถามคำถาม เช่น เหตุใดจึงจำเป็นต้องใช้เธรด วิธีสร้างเธรด วิธีใดในการสร้างเธรดจะดีกว่า สืบทอดจาก Thread หรือใช้ Runnable จากนั้นค่อย ๆ ดำเนินการ เกี่ยวกับความยากลำบากของการทำงานพร้อมกัน ความยากลำบากที่พบในการพัฒนาแอปพลิเคชันแบบขนาน ยูทิลิตี้การทำงานพร้อมกันระดับสูงที่นำมาใช้ใน JDK 1.5 หลักการและรูปแบบการออกแบบของแอปพลิเคชันแบบขนาน และปัญหามัลติเธรดแบบคลาสสิก เพียงเพราะการรู้พื้นฐานของมัลติเธรดนั้นไม่เพียงพอ คุณต้องรู้วิธีจัดการกับปัญหาการทำงานพร้อมกัน เช่น การหยุดชะงัก สภาวะการแข่งขัน ความไม่สอดคล้องกันของหน่วยความจำ และปัญหาด้านความปลอดภัยของเธรดต่างๆ ทักษะเหล่านี้ได้รับการทดสอบอย่างละเอียด นำเสนอความท้าทายด้านมัลติเธรดและการทำงานพร้อมกันต่างๆ Java Developer หลายๆ คนมักจะแค่อ่านคำถามก่อนการสัมภาษณ์ ซึ่งก็ไม่ใช่เรื่องแย่ แต่คุณควรเข้าใจเรื่องนี้ นอกจากนี้การรวบรวมคำถามและทำแบบฝึกหัดเดียวกันนั้นทำให้เสียเวลามาก ฉันจึงสร้างรายการนี้ขึ้นมา
GO TO FULL VERSION