1. แนวคิดพื้นฐานของเธรด
ความเข้าใจเธรด: เธรดเป็นเส้นทางการดำเนินการที่แตกต่างกันในโปรแกรม
แต่ละสาขาเรียกว่าด้ายและ Main () เรียกว่าสาขาหลักหรือที่เรียกว่าด้ายหลัก
กระบวนการเป็นเพียงแนวคิดแบบคงที่ไฟล์. class บนเครื่องไฟล์. exe บนเครื่องซึ่งเรียกว่ากระบวนการ กระบวนการดำเนินการของโปรแกรมเป็นเช่นนี้: ก่อนอื่นใส่รหัสของโปรแกรมลงในพื้นที่รหัสของหน่วยความจำ หลังจากวางรหัสไว้ในพื้นที่รหัสแล้วจะไม่เริ่มดำเนินการทันที อย่างไรก็ตามนี่หมายความว่ากระบวนการพร้อมที่จะเริ่มต้น กระบวนการนี้ถูกสร้างขึ้น แต่ยังไม่ได้เริ่มดำเนินการ นี่คือกระบวนการดังนั้นกระบวนการจึงเป็นแนวคิดที่คงที่และไม่สามารถเคลื่อนย้ายได้ด้วยตัวเอง กระบวนการดำเนินการตามปกติหมายถึงเธรดหลักในกระบวนการที่เริ่มดำเนินการนั่นคือวิธีการหลัก () เริ่มดำเนินการ กระบวนการเป็นแนวคิดแบบคงที่และเธรดจริงทำงานในเครื่องของเรา
ระบบปฏิบัติการ Windows รองรับมัลติเธรด มันสามารถเรียกใช้เธรดจำนวนมากในเวลาเดียวกันและยังรองรับหลายกระบวนการ ดังนั้นระบบปฏิบัติการ Windows จึงเป็นระบบปฏิบัติการที่รองรับการทำมัลติเธรดและหลายการประมวลผล Linux และ Uinux ยังเป็นระบบปฏิบัติการที่รองรับมัลติเธรดและการประมวลผลแบบหลายครั้ง DOS ไม่รองรับมัลติเธรดและการประมวลผลหลายครั้ง รองรับกระบวนการเดียวเท่านั้น กระบวนการเดียวเท่านั้นที่ดำเนินการในเวลาเดียวกันซึ่งเรียกว่าการเธรดเดี่ยว
CPU มีพลังมากและสามารถเรียกใช้โปรแกรมมากมายในเวลาเดียวกันได้หรือไม่? ไม่การดำเนินการของ CPU มีดังนี้ CPU นั้นเร็วมากและสามารถนับได้หลายร้อยล้านครั้งในวินาทีดังนั้น CPU จึงแบ่งเวลาออกเป็นชิ้นเล็ก ๆ ฉันดำเนินการในเวลานี้สักพักหนึ่งในครั้งต่อไปชิ้นจะดำเนินการสักพักหนึ่งและในครั้งต่อไปชิ้นจะดำเนินการอื่น ๆ ในขณะที่ แม้ว่าจะมีเธรดหลายสิบเธรด แต่ก็สามารถดำเนินการทั้งหมดได้ในเวลาอันสั้น แต่สำหรับมนุษย์เราความเร็วในการดำเนินการของ CPU นั้นเร็วเกินไปดังนั้นดูเหมือนว่ามันจะดำเนินการในเวลาเดียวกัน แต่ในความเป็นจริงในเวลาหนึ่งมีเธรดเดียวเท่านั้นที่ทำงานบนซีพียู
ก่อนอื่นคุณต้องเข้าใจแนวคิดสามประการเมื่อเรียนรู้หัวข้อ :
1. กระบวนการ: กระบวนการเป็นแนวคิดแบบคงที่
2. เธรด: มีเธรดหลักในกระบวนการที่เรียกว่า Main () ซึ่งเป็นโปรแกรมและเส้นทางการดำเนินการที่แตกต่างกันในกระบวนการ
3. ในเวลาเดียวกัน CPU สามารถรองรับหนึ่งเธรดหนึ่งเธรดเพื่อดำเนินการ เนื่องจากซีพียูทำงานเร็วมากเราจึงดูเหมือนว่าเรากำลังมัลติเธรด
มัลติเธรดจริงคืออะไร? หากเครื่องของคุณมีซีพียูคู่หรือแกนคู่มันเป็นแบบมัลติเธรด
2. การสร้างและการเริ่มต้นของเธรด
ใน Java เธรด Java จะถูกนำไปใช้ผ่านคลาส java.lang.thread และแต่ละวัตถุเธรดแสดงถึงเธรดใหม่ มีสองวิธีในการสร้างเธรดใหม่: สิ่งแรกคือการสืบทอดจากคลาสเธรดและอีกวิธีหนึ่งคือการใช้อินเตอร์เฟสที่รันได้ เมื่อ VM เริ่มต้นจะมีเธรดที่กำหนดโดยวิธีหลัก (โมฆะคงที่สาธารณะหลัก ()) และเธรดนี้เรียกว่าเธรดหลัก เธรดใหม่สามารถสร้างขึ้นได้โดยการสร้างอินสแตนซ์ของเธรด คุณเพียงแค่ต้องใช้วัตถุเธรดใหม่และเธรดใหม่จะปรากฏขึ้น แต่ละเธรดเสร็จสิ้นการดำเนินการผ่านวิธีการเรียกใช้ () ที่สอดคล้องกับวัตถุเธรดเฉพาะ วิธีการเรียกใช้ () เรียกว่าร่างกายด้าย
ตัวอย่างที่ 1: สร้างและเริ่มเธรดใหม่โดยใช้การใช้งานอินเทอร์เฟซ Runnable
สร้างเธรดใหม่เพื่อเรียกวิธีการเรียกใช้
แพ็คเกจ cn.galc.test; Public Class TestThread1 {โมฆะคงที่สาธารณะหลัก (สตริง args []) {runner1 r1 = new runner1 (); // ที่นี่วัตถุใหม่ของคลาสเธรดออกมา // r1.run (); // นี่เรียกว่าวิธีการโทร การดำเนินการของการเรียกใช้วิธีคือรอจนกว่าวิธีการเรียกใช้ () จะถูกดำเนินการก่อนที่วิธีการหลัก () จะดำเนินการต่อไป เธรด t = เธรดใหม่ (r1); // ในการเริ่มเธรดใหม่คุณต้องใช้วัตถุเธรดใหม่ออกมา // เธรด (เป้าหมายที่เรียกใช้ได้) ที่นี่ ตัวสร้าง t.start (); // เริ่มเธรดที่เปิดใหม่เธรดใหม่จะดำเนินการวิธีการเรียกใช้ () และเธรดใหม่และเธรดหลักจะดำเนินการในแบบขนานสำหรับ (int i = 0; i <10; i ++) {system.out.println ("maintheod:"+i); }}}/*กำหนดคลาสเพื่อใช้งานอินเตอร์เฟส Runnable การใช้งานอินเตอร์เฟส Runnable หมายความว่าคลาสนี้เป็นคลาสเธรด*/คลาส runner1 ใช้งาน runnable {public void run () {สำหรับ (int i = 0; i <10; i ++) {system.out.println ("runner1:"+i); -กระบวนการดำเนินการของโปรแกรมมัลติเธรดมีดังนี้:
เรียกวิธีการเรียกใช้โดยตรงโดยไม่ต้องเปิดเธรดใหม่
ผลการดำเนินการมีดังนี้:
ตัวอย่างที่ 2: สืบทอดคลาสเธรดและแทนที่เมธอด Run () เพื่อสร้างและเริ่มเธรดใหม่
แพ็คเกจ cn.galc.test;/*วิธีที่สองของการสร้างเธรดและการเริ่มต้น: กำหนดคลาสย่อยของเธรดและใช้วิธีการเรียกใช้ ()*/คลาสสาธารณะ testThread2 {โมฆะคงที่สาธารณะหลัก (สตริง args []) {runner2 r2 = new runner2 (); r2.start (); // เรียกเมธอด start () เพื่อเริ่มเธรดที่เปิดใหม่สำหรับ (int i = 0; i <= 10; i ++) {system.out.println ("MainMethod:"+i); }}}/*คลาส runner2 ที่สืบทอดมาจากคลาสเธรดโดยการสร้างอินสแตนซ์วัตถุของคลาส runner2 คุณสามารถเปิดเธรดใหม่ เรียกวิธีการเริ่มต้น () ที่สืบทอดมาจากคลาสเธรด คุณสามารถเริ่มต้นเธรดที่เปิดใหม่*/คลาส runner2 ขยายเธรด {public void run () {// rewrite การใช้วิธีการเรียกใช้ () สำหรับ (int i = 0; i <= 10; i ++) {system.out.println ("runner2:"+i); -ทางเลือกในการใช้สองวิธีในการสร้างเธรดใหม่คือการใช้อินเตอร์เฟสที่เรียกใช้งานได้และการสืบทอดคลาสเธรดควรได้รับความสำคัญในการเปิดเธรดใหม่ เนื่องจากการใช้งานอินเทอร์เฟซสามารถใช้งานได้หลายอย่างการสืบทอดของคลาสจึงสามารถสืบทอดได้เพียงครั้งเดียว ดังนั้นเมื่อคุณสามารถใช้อินเทอร์เฟซ Runnable เมื่อเปิดเธรดใหม่ให้พยายามอย่าใช้การสืบทอดจากคลาสเธรดเพื่อเปิดเธรดใหม่
3. การเปลี่ยนแปลงสถานะเธรด
3.1. วิธีพื้นฐานของการควบคุมเธรด
3.2. เบื้องต้นเกี่ยวกับวิธีการนอนหลับ/เข้าร่วม/ผลผลิต
ตัวอย่างการประยุกต์ใช้วิธีการนอนหลับ:
แพ็คเกจ cn.galc.test; นำเข้า Java.util.*; Public Class TestThread3 {โมฆะคงที่สาธารณะหลัก (สตริง args []) {เธรด MYTHREAD = ใหม่ MyThread (); thread.start (); // เรียกเมธอด start () เพื่อเริ่มเธรดที่เปิดใหม่ลอง {/*thread.sleep(10000); วิธีการ sleep () เป็นวิธีการคงที่ที่ประกาศในคลาสเธรดดังนั้นคุณสามารถใช้รูปแบบของ thread.sleep () เพื่อโทร * / /*mythread.sleep(10000); คลาส MyThread สืบทอดคลาสเธรดและตามธรรมชาติยังสืบทอดวิธีการนอนหลับ () ดังนั้นคุณยังสามารถเรียกมันว่าโดยใช้รูปแบบของ mythread.sleep () *// *การเรียกใช้วิธีการคงที่สามารถเรียกได้โดยตรงในรูปแบบของ "ชื่อคลาสชื่อวิธีการ" หรือ "การอ้างอิงวัตถุ System.out.println ("เธรดหลักนอนเป็นเวลา 10 วินาทีและเริ่มต้นอีกครั้ง"); // เมื่อเรียกวิธีการคงที่ของคลาสอื่นในวิธีการหลัก () คุณจะต้องใช้ชื่อ "คลาสเมธอดแบบคงที่ซึ่งวิธีการคงที่" วิธีการโทร /* ดังนั้นที่นี่คือการปล่อยให้เธรดหลักนอนหลับเป็นเวลา 10 วินาที เธรดใดเรียกวิธีการนอนหลับ () ดังนั้นตอนนี้เธรดหลักจะนอนหลับ */} catch (interruptedException e) {e.printStackTrace (); } //thread.interrupt();//use Interrupt () วิธีการสิ้นสุดการดำเนินการของเธรดเธรด flag = false; // เปลี่ยนเงื่อนไขการวนซ้ำและสิ้นสุดการวนซ้ำที่ตายแล้ว/** * เมื่อมีการขัดจังหวะการตั้งค่าโดยตรงตั้งค่าลูปให้เท็จ นี่เป็นวิธีที่ดีกว่าในการจบเธรดลูก* / / *** วิธีการโทร Interrupt () เพื่อทำลายเธรดที่รันนั้นเทียบเท่ากับการเทหม้อน้ำเย็นลงบนด้ายหลักและทำลายเธรดย่อยที่ดำเนินการ หลังจากการเรียกใช้การดำเนินการย่อยการดำเนินการถูกขัดจังหวะการขัดจังหวะการรับรู้จะถูกโยนลงซึ่งจะดำเนินการคำสั่ง Return และสิ้นสุดการดำเนินการของเธรด ดังนั้นเธรดย่อยที่นี่จะสิ้นสุดการดำเนินการของเธรดหลังจาก 10 วินาทีของการดำเนินการ */}} คลาส Mythread ขยายเธรด {ธงบูลีน = true; // กำหนดแท็กเพื่อควบคุมเงื่อนไขของการวนซ้ำของลูปสาธารณะ ข้อยกเว้นมากกว่าวิธีที่เขียนใหม่ * ดังนั้นที่นี่คุณสามารถเขียนลอง ... catch () เพื่อจับข้อยกเว้น*/ ในขณะที่ (ธง) { System.out.println ("======================================================================================================================== - - - - - - แน่นอนว่ามันไม่ผิดที่จะเรียกมันโดยใช้รูปแบบของ "ชื่อคลาสชื่อวิธี"*/ // mythread.sleep (1,000); // ใช้รูปแบบของ "ชื่อคลาสชื่อวิธี" เพื่อเรียกวิธีการคงที่ (1000); // ถ้ามันถูกขัดจังหวะในระหว่างการนอนหลับ ในการวนซ้ำที่ตายแล้วและเวลาของระบบปัจจุบันถูกพิมพ์ออกมาในแต่ละวินาที} catch (interruptedException E) { /** เมื่อนอนหลับแผ่นน้ำเย็นอาจขัดจังหวะการนอนหลับ* ดังนั้นเมื่อด้ายวิ่งถูกขัดจังหวะด้วยเหตุผลที่ไม่คาดคิดข้อยกเว้นที่ถูกขัดจังหวะผลการทำงาน:
ตัวอย่างของวิธีการเข้าร่วม:
แพ็คเกจ cn.galc.test; Public Class TestThread4 {โมฆะคงที่สาธารณะหลัก (String args []) {mythread2 thread2 = ใหม่ mythread2 ("Mythread"); // ในขณะที่การสร้างวัตถุเธรดใหม่ตั้งชื่อวัตถุเธรด Object MyThread Thread2.start (); // เริ่มเธรดลอง {thread2.join (); // เรียกวิธีการเข้าร่วม () เพื่อรวมเธรดให้ผสานเธรดลูก mythread เข้ากับเธรดหลัก // หลังจากการรวมเธรด } สำหรับ (int i = 0; i <= 5; i ++) {system.out.println ("ฉันเป็นเธรดหลัก"); }}} คลาส mythread2 ขยายเธรด {mythread2 (สตริง s) {super (s); / * * ใช้คำหลัก Super เพื่อเรียกตัวสร้างของคลาสแม่ * หนึ่งในตัวสร้างของเธรดคลาสแม่: "เธรดสาธารณะ (ชื่อสตริง)" * ผ่านตัวสร้างดังกล่าวสามารถตั้งชื่อเธรดที่เปิดใหม่ได้ซึ่งสามารถอำนวยความสะดวกในการจัดการเธรด */} getName ()); // ใช้ // public final String getName () ที่กำหนดไว้ในเธรดคลาสแม่, ส่งคืนชื่อเธรดนี้ ลอง {sleep (1,000); // ทำให้ด้ายลูกนอนเป็นเวลา 1 วินาทีทุกครั้งที่ดำเนินการ} catch (interruptedException e) {return; -ผลการทำงาน:
ตัวอย่างการใช้วิธีการให้ผลผลิต:
แพ็คเกจ cn.galc.test; Public Class TestThread5 {โมฆะคงที่สาธารณะหลัก (String args []) {MyThread3 T1 = ใหม่ MyThread3 ("T1"); /* สองเธรดลูก T1 และ T2 ถูกเปิดในเวลาเดียวกัน T1 และ T2 ทั้งสองดำเนินการวิธีการเรียกใช้ ()*//*มีทั้งหมด 3 เธรดในแบบขนานระหว่างการดำเนินการของโปรแกรมนี้คือเธรดเด็ก T1 และ T2 และเธรดหลัก*/ mythread3 T2 = ใหม่ Mythread3 ("T2"); t1.start (); // ด้ายลูกสตาร์ท t1 t2.start (); // ด้ายลูกสตาร์ท t2 สำหรับ (int i = 0; i <= 5; i ++) {system.out.println ("ฉันเป็นเธรดหลัก"); }}} คลาส mythread3 ขยายเธรด {mythread3 (สตริง s) {super (s); } โมฆะสาธารณะเรียกใช้ () {สำหรับ (int i = 1; i <= 5; i ++) {system.out.println (getName () + ":" + i); if (i % 2 == 0) {deltm (); // เมื่อการดำเนินการถึงฉันสามารถแบ่งออกเป็น 2 การดำเนินการเธรดปัจจุบันจะถูกส่งออกและปล่อยให้เธรดอื่นดำเนินการวิธีการเรียกใช้ () จะถูกดำเนินการก่อน/ * * คุณสามารถเห็นในระหว่างการทำงานของโปรแกรม * เมื่อเธรด t1 ถูกดำเนินการ (i % 2 == 0) (i%2 == 0) ครั้งมันจะให้เธรดกับเธรด T1 กับการดำเนินการลำดับความสำคัญ */}}}ผลการดำเนินการมีดังนี้:
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ เราหวังว่ามันจะช่วยคุณได้