ปัญหาที่มัลติเธรดแก้ไขใน Java
โดยพื้นฐานแล้ว Java multithreading ได้รับการคิดค้นขึ้นเพื่อแก้ไขปัญหาหลักสองประการ:-
ดำเนินการหลายอย่างพร้อมกัน
ในตัวอย่างข้างต้น หัวข้อต่างๆ (เช่น สมาชิกในครอบครัว) ดำเนินการหลายอย่างพร้อมกัน เช่น ล้างจาน ไปที่ร้าน พับสิ่งของ
สามารถให้ตัวอย่าง "โปรแกรมเมอร์" เพิ่มเติมได้ ลองนึกภาพว่าคุณมีโปรแกรมที่มีส่วนต่อประสานกับผู้ใช้ เมื่อคลิกปุ่มดำเนินการต่อ การคำนวณบางอย่างควรเกิดขึ้นภายในโปรแกรม และผู้ใช้ควรเห็นหน้าจออินเทอร์เฟซต่อไปนี้ หากดำเนินการเหล่านี้ตามลำดับหลังจากคลิกปุ่ม "ดำเนินการต่อ" โปรแกรมก็จะหยุดทำงาน ผู้ใช้จะเห็นหน้าจอเดียวกันกับปุ่ม "ดำเนินการต่อ" จนกว่าการคำนวณภายในทั้งหมดจะเสร็จสิ้นและโปรแกรมจะไปถึงส่วนที่จะเริ่มวาดอินเทอร์เฟซ
รอสองสามนาที!
เรายังสามารถสร้างโปรแกรมของเราใหม่ได้ หรืออย่างที่โปรแกรมเมอร์พูดว่า "ขนานกัน" ปล่อยให้การคำนวณที่จำเป็นดำเนินการในเธรดหนึ่ง และแสดงผลอินเทอร์เฟซในอีกเธรดหนึ่ง คอมพิวเตอร์ส่วนใหญ่มีทรัพยากรเพียงพอสำหรับสิ่งนี้ ในกรณีนี้โปรแกรมจะไม่ "โง่" และผู้ใช้จะย้ายไปมาระหว่างหน้าจออินเทอร์เฟซอย่างใจเย็นโดยไม่ต้องกังวลกับสิ่งที่เกิดขึ้นภายใน มันไม่รบกวน :)
-
เร่งความเร็วในการคำนวณ
ทุกอย่างง่ายกว่ามากที่นี่ หากโปรเซสเซอร์ของเรามีหลายคอร์ และตอนนี้โปรเซสเซอร์ส่วนใหญ่เป็นแบบมัลติคอร์ รายการงานของเราสามารถแก้ไขได้แบบขนานด้วยคอร์หลายคอร์ แน่นอนว่าหากเราจำเป็นต้องแก้ปัญหา 1,000 ปัญหาและแต่ละปัญหาได้รับการแก้ไขในหนึ่งวินาที หนึ่งคอร์จะจัดการกับรายการได้ภายใน 1,000 วินาที สองคอร์ในเวลา 500 วินาที สามคอร์ในเวลาเพียง 333 วินาที และอื่นๆ
Thread
พูดอย่างเคร่งครัด เธรดใน Java ถูกแสดงโดยอินสแตนซ์ของคลาส นั่นคือ ในการสร้างและรัน 10 เธรด คุณจะต้องมี 10 อ็อบเจ็กต์ของคลาสนี้ ลองเขียนตัวอย่างที่ง่ายที่สุด:
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("I'm Thread! My name is " + getName());
}
}
ในการสร้างและเปิดเธรด เราจำเป็นต้องสร้างคลาสและสืบทอดจากไฟล์java.lang
. Thread
และแทนที่วิธีการในrun()
นั้น อันสุดท้ายมีความสำคัญมาก มันอยู่ในวิธีการที่run()
เรากำหนดตรรกะที่เธรดของเราต้องดำเนินการ ตอนนี้ ถ้าเราสร้างอินสแตนซ์MyFirstThread
และรันมัน เมธอดrun()
จะพิมพ์บรรทัดที่มีชื่อของมันไปที่คอนโซล: เมธอดgetName()
จะพิมพ์ชื่อ “ระบบ” ของเธรด ซึ่งถูกกำหนดโดยอัตโนมัติ แม้ว่าที่จริงแล้วทำไมถึง “ถ้า”? มาสร้างและทดสอบกันเถอะ!
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
เอาต์พุตคอนโซล: ฉันเป็นเธรด! ฉันชื่อ Thread-2 ฉัน Thread! ฉันชื่อ Thread-1 ฉันชื่อ Thread! ฉันชื่อ Thread-0 ฉันชื่อ Thread! ฉันชื่อเธรด-3 ฉันเธรด! ฉันชื่อเธรด-6 ฉันเธรด! ฉันชื่อ Thread-7 ฉันชื่อ Thread! ฉันชื่อ Thread-4 ฉันชื่อ Thread! ฉันชื่อ Thread-5 ฉันชื่อ Thread! ฉันชื่อเธรด-9 ฉันเธรด! ชื่อของฉันคือ Thread-8 เราสร้าง 10 เธรด (วัตถุ) MyFirstThread
ที่สืบทอดมาThread
และเปิดใช้งานโดยการเรียกเมธอดของวัตถุ start()
หลังจากเรียกเมธอดแล้วstart()
เมธอดของมันก็เริ่มทำงานrun()
และตรรกะที่เขียนไว้ก็ถูกดำเนินการ โปรดทราบ: ชื่อเธรดไม่อยู่ในลำดับ มันค่อนข้างแปลก ทำไมพวกเขาไม่ถูกประหารชีวิตตามลำดับ: Thread-0
, Thread-1
, Thread-2
และอื่นๆ? นี่เป็นตัวอย่างที่ชัดเจนเมื่อการคิดแบบ "ต่อเนื่อง" แบบมาตรฐานจะไม่ทำงาน ความจริงก็คือในกรณีนี้เราจะออกคำสั่งเพื่อสร้างและเปิดใช้งาน 10 เธรดเท่านั้น ลำดับที่ควรเปิดตัวจะถูกตัดสินใจโดยตัวกำหนดตารางเวลาเธรด: กลไกพิเศษภายในระบบปฏิบัติการ โครงสร้างนี้มีโครงสร้างอย่างไรและหลักการใดในการตัดสินใจนั้นเป็นหัวข้อที่ซับซ้อนมากและเราจะไม่เจาะลึกในตอนนี้ สิ่งสำคัญที่ต้องจำคือโปรแกรมเมอร์ไม่สามารถควบคุมลำดับการทำงานของเธรดได้ เพื่อให้ทราบถึงความร้ายแรงของสถานการณ์ ให้ลองใช้วิธีการmain()
จากตัวอย่างด้านบนอีกสองสามครั้ง เอาต์พุตคอนโซลที่สอง: ฉันเป็น Thread! ฉันชื่อ Thread-0 ฉันชื่อ Thread! ฉันชื่อ Thread-4 ฉันชื่อ Thread! ฉันชื่อเธรด-3 ฉันเธรด! ฉันชื่อ Thread-2 ฉัน Thread! ฉันชื่อ Thread-1 ฉันชื่อ Thread! ฉันชื่อ Thread-5 ฉันชื่อ Thread! ฉันชื่อเธรด-6 ฉันเธรด! ฉันชื่อ Thread-8 ฉันชื่อ Thread! ฉันชื่อเธรด-9 ฉันเธรด! ชื่อของฉันคือ Thread-7 เอาต์พุตคอนโซลที่สาม: ฉันชื่อ Thread! ฉันชื่อ Thread-0 ฉันชื่อ Thread! ฉันชื่อเธรด-3 ฉันเธรด! ฉันชื่อ Thread-1 ฉันชื่อ Thread! ฉันชื่อ Thread-2 ฉัน Thread! ฉันชื่อเธรด-6 ฉันเธรด! ฉันชื่อ Thread-4 ฉันชื่อ Thread! ฉันชื่อเธรด-9 ฉันเธรด! ฉันชื่อ Thread-5 ฉันชื่อ Thread! ฉันชื่อ Thread-7 ฉันชื่อ Thread! ฉันชื่อ กระทู้-8
ปัญหาที่มัลติเธรดสร้างขึ้น
ในตัวอย่างในหนังสือ คุณเห็นว่ามัลติเธรดช่วยแก้ปัญหาที่สำคัญได้ และการใช้งานทำให้โปรแกรมของเราเร็วขึ้น ในหลายกรณี-หลายครั้ง แต่ไม่ใช่เพื่ออะไรที่มัลติเธรดถือเป็นหัวข้อที่ซับซ้อน เพราะหากใช้ไม่ถูกต้องจะสร้างปัญหาแทนที่จะแก้ไข เมื่อฉันพูดว่า “สร้างปัญหา” ฉันไม่ได้หมายถึงสิ่งที่เป็นนามธรรม มีปัญหาเฉพาะสองประการที่อาจทำให้เกิดมัลติเธรด: การหยุดชะงักและสภาวะการแข่งขัน การหยุดชะงักเป็นสถานการณ์ที่หลายเธรดกำลังรอทรัพยากรที่ครอบครองโดยกันและกัน และไม่มีเธรดใดที่สามารถดำเนินการต่อไปได้ เราจะพูดถึงเรื่องนี้เพิ่มเติมในการบรรยายครั้งต่อไป แต่สำหรับตอนนี้ตัวอย่างนี้ก็เพียงพอแล้ว:
- Thread-1 จะหยุดทำงานกับ Object-1 และสลับไปที่ Object-2 ทันทีที่ Thread-2 หยุดทำงานกับ Object 2 และสลับไปที่ Object-1
- Thread-2 จะหยุดทำงานกับ Object-2 และสลับไปที่ Object-1 ทันทีที่ Thread-1 หยุดทำงานกับ Object 1 และสลับไปที่ Object-2

public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("Выполнен поток " + getName());
}
}
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
ทีนี้ลองจินตนาการว่าโปรแกรมมีหน้าที่รับผิดชอบการทำงานของหุ่นยนต์ที่เตรียมอาหาร! Thread-0 นำไข่ออกจากตู้เย็น สตรีม 1 รอบบนเตา Stream-2 หยิบกระทะออกมาวางบนเตา สตรีม 3 จุดไฟบนเตา สตรีมที่ 4 เทน้ำมันลงในกระทะ สตรีม 5 ตอกไข่และเทลงในกระทะ สตรีม 6 โยนเชลล์ลงถังขยะ Stream-7 จะนำไข่กวนที่เสร็จแล้วออกจากเตา Potok-8 ตักไข่คนใส่จาน สตรีม-9 ล้างจาน ดูผลลัพธ์ของโปรแกรมของเรา: ดำเนินการ Thread-0 ดำเนินการเธรด-2 ดำเนินการเธรด ดำเนินการเธรด-1 ดำเนินการเธรด ดำเนินการเธรด-4 ดำเนินการเธรด เธรด-9 ดำเนินการเธรด ดำเนินการเธรด-5 ดำเนินการเธรด เธรด-8 ดำเนินการเธรด ดำเนินการเธรด-7 ดำเนินการเธรด เธรด-7 ดำเนินการเธรด -3 เธรด-6 ดำเนินการเธรด สคริปต์สนุกไหม? :) และทั้งหมดเป็นเพราะการทำงานของโปรแกรมของเราขึ้นอยู่กับลำดับการดำเนินการของเธรด เมื่อมีการละเมิดซีเควนซ์เพียงเล็กน้อย ห้องครัวของเราก็กลายเป็นนรก และหุ่นยนต์บ้าคลั่งก็ทำลายทุกสิ่งรอบตัว นี่เป็นปัญหาทั่วไปในการเขียนโปรแกรมแบบมัลติเธรดซึ่งคุณจะได้ยินมากกว่าหนึ่งครั้ง ในช่วงท้ายของการบรรยาย ผมอยากจะแนะนำหนังสือเกี่ยวกับมัลติเธรดให้กับคุณ

GO TO FULL VERSION