ฉันได้แนะนำการใช้มัลติเธรด Java สั้น ๆ ฉันได้แนะนำคลาสเธรดและคลาสที่เรียกใช้ได้แล้ว เพื่อให้เข้าใจมัลติเธรดได้ดีขึ้นบทความนี้จะทำการวิเคราะห์อย่างละเอียดของเธรด
เริ่ม()
ก่อนอื่นมาดูการแนะนำวิธีนี้ใน API:
ทำให้เธรดเริ่มดำเนินการ; เครื่องเสมือน Java เรียกใช้วิธีการเรียกใช้เธรด
ผลที่ได้คือสองเธรดทำงานพร้อมกัน เธรดปัจจุบัน (ส่งคืนจากการโทรไปยังวิธีการเริ่มต้น) และเธรดอื่น ๆ (ดำเนินการวิธีการเรียกใช้)
มันผิดกฎหมายที่จะเริ่มต้นด้ายหลายครั้ง โดยเฉพาะอย่างยิ่งเมื่อเธรดเสร็จสิ้นการดำเนินการเสร็จแล้วมันไม่สามารถรีสตาร์ทได้
ใช้วิธีการเริ่มต้นเพื่อเริ่มต้นเธรดซึ่งตระหนักถึงมัลติเธรดอย่างแท้จริง ในเวลานี้คุณไม่จำเป็นต้องรอรหัสการเรียกใช้ Body Code เพื่อดำเนินการเสร็จสิ้นและดำเนินการต่อเพื่อดำเนินการรหัสต่อไปนี้โดยตรง เธรดเริ่มต้นโดยการเรียกวิธีการเริ่มต้น () ของคลาสเธรด ในเวลานี้เธรดอยู่ในสถานะพร้อม (เรียกใช้งานได้) และไม่ทำงาน เมื่อได้รับชิ้นเวลา CPU วิธีการเรียกใช้ () จะเริ่มดำเนินการ ที่นี่วิธีการเรียกใช้ () เรียกว่าร่างกายด้าย มันมีเนื้อหาของเธรดที่จะดำเนินการ วิธีการเรียกใช้สิ้นสุดและเธรดจะสิ้นสุดลงทันที
วิธีการเริ่มต้นเป็นวิธีการเริ่มต้นเธรด หลังจากใช้งานแล้ว Java จะสร้างเธรดใหม่เพื่อเรียกใช้วิธีการทำงาน นี่คือการสาธิตเล็ก ๆ :
สำหรับ (int i = 0; i <3; i ++) {เธรด t = เธรดใหม่ (ใหม่ runnable () {@Override โมฆะสาธารณะเรียกใช้ () {system.out.println (thread.currentthread (). getName ()+"เริ่ม"); System.out.println (thread.currentthread (). getName ()+"end"); T.Start (); } system.out.println ("มันจบ"); ผลการดำเนินการ:
มันจบลงแล้ว
เริ่มต้นเธรด -1
เธรด -0 เริ่มต้น
เริ่มเธรด -2
ด้าย -0 สิ้นสุด
End thread-1
ปลายด้าย -2 สิ้นสุด
เนื่องจากมัลติเธรดเป็นแบบสุ่มผลลัพธ์อาจแตกต่างกันในแต่ละครั้งซึ่งเป็นสิ่งที่เราต้องใส่ใจ ลำดับการดำเนินการและลำดับการโทรของเธรดไม่สอดคล้องกัน
วิ่ง()
วิธีการเรียกใช้คือการเรียกใช้วิธีการเรียกใช้ของ Set Runnable โดยเธรดและแก้ไขการสาธิตด้านบน:
สำหรับ (int i = 0; i <3; i ++) {เธรด t = เธรดใหม่ (ใหม่ runnable () {@Override โมฆะสาธารณะเรียกใช้ () {system.out.println (thread.currentthread (). getName ()+"เริ่ม"); System.out.println (thread.currentthread (). getName ()+"end"); t.run (); } system.out.println ("มันจบ"); ผลการดำเนินการ:
การเริ่มต้นหลัก
จุดจบ
การเริ่มต้นหลัก
จุดจบ
การเริ่มต้นหลัก
จุดจบ
มันจบลงแล้ว
ผลลัพธ์โดยตรงของวิธีการวิ่งนั้นแตกต่างจากจุดเริ่มต้นมาก มันถูกดำเนินการตามลำดับและไม่เปิดเธรดใหม่
หยุด()
วิธีการหยุดคือการบังคับหยุดการดำเนินการของเธรด ไม่ปลอดภัยดังนั้นอย่าใช้วิธีนี้ เมื่อมีการเรียกว่าหยุดทรัพยากรที่ถูกล็อคจะถูกปล่อยออกมา แต่รุ่นนี้ไม่สอดคล้องกันและสามารถทำให้เกิดปัญหาโปรแกรมได้อย่างง่ายดาย หากคุณต้องการควบคุมการหยุดของเธรดคุณสามารถใช้ตัวแปรที่กำหนดเองเพื่อตัดสินหรือวิธีการ isinterrupted ():
คลาส Thread1 ขยายเธรด {@Override public void run () {// ตัดสินว่าร่างกายของเธรดกำลังทำงานอยู่ในขณะที่ (! isInterrupted ()) {// ทำอะไร}}} ขัดจังหวะ()
ฟังก์ชั่นของการขัดจังหวะคือการแจ้งเธรดที่คุณถูกขัดจังหวะ แต่การดำเนินการขัดจังหวะที่เฉพาะเจาะจงนั้นต้องใช้การประมวลผลที่กำหนดเองของเธรดและคุณสามารถเพิกเฉยต่อและดำเนินการต่อได้ ความเหงาที่เฉพาะเจาะจงคือการโยนการขัดจังหวะการรับรู้เมื่อเธรดการดำเนินการเข้าร่วมรอและวิธีการนอนหลับ
เธรด t1 = เธรดใหม่ (ใหม่ runnable () {@Override โมฆะสาธารณะ run () {system.out.println (thread.currentthread (). getName ()+"start"); ลอง {สำหรับ (int i = 0; i <100000; System.out.println ("เธรดถูกขัดจังหวะ"); // คุณสามารถทำการปล่อยทรัพยากรการบันทึก ฯลฯ E.PrintStackTrace (); t1.start (); Thread.sleep (100); t1.interrupt ();ผลการดำเนินการ:
65666768 เธรดถูกขัดจังหวะ java.lang.interruptedException: การนอนหลับ interruptedThread-0 สิ้นสุดที่ java.lang.thread.sleep (วิธีการดั้งเดิม) ที่ com.wk.aqi.act.test $ 1.run (test.java:23) ที่ Java.lang.lang.lang.lang
isinterrupted ()
เพื่อตรวจสอบว่าเธรดถูกขัดจังหวะหรือไม่หลังจากดำเนินการวิธีการขัดจังหวะข้างต้นมันจะส่งคืนจริง
setPriority (int newpriority) และ getPriority ()
ตั้งค่าลำดับความสำคัญของเธรดและรับลำดับความสำคัญของเธรด ทรัพยากรที่จัดสรรโดย CPU มุ่งเน้นไปที่เธรดที่มีลำดับความสำคัญสูงกว่า
เธรด t1 = เธรดใหม่ (ใหม่ runnable () {@Override โมฆะสาธารณะ run () {long t = system.currentTimeMillis (); system.out.println (thread.currentthread (). getName ()+"start"); บล็อก catch ที่สร้างขึ้นอัตโนมัติ E.PrintStackTrace ();}} system.out.println (thread.currentthread (). getName ()+"t1 end"+(system.currenttimeLis ()-t)); เธรด t2 = เธรดใหม่ (ใหม่ runnable () {@Override โมฆะสาธารณะ run () {long t = system.currentTimeMillis (); system.out.println (thread.currentthread (). getName ()+"เริ่ม"); สำหรับ (int i = 0; TODO Catch Block ที่สร้างขึ้นอัตโนมัติ E.PrintStackTrace ();}} System.out.println (thread.currentthread (). getName ()+"t2 end"+(system.currentTimeLis ()-t)); T1.SetPriority (10); T2.SetPriority (1); t2.start (); t1.start ();ผลการดำเนินการ:
เธรด -0 startthread-1 startthread-0 t1 end 1357Thread-1 t2 end 1371
เมื่อลำดับความสำคัญเหมือนกัน T1 และ T2 จะเสร็จสมบูรณ์เกือบจะในเวลาเดียวกันและมีความแตกต่างที่ชัดเจนเมื่อลำดับความสำคัญแตกต่างกัน
getName ()
มันค่อนข้างง่ายรับชื่อของเธรด
เข้าร่วม () และเข้าร่วม (มิลลิสยาว)
ฟังก์ชั่นของวิธี Jion คือรอให้การดำเนินการเธรดเสร็จสมบูรณ์และเข้าร่วม (มิลลิสยาว) สามารถตั้งค่าเวลารอสูงสุดได้ ตัวอย่างเช่นเธรดหลักจำเป็นต้องรอให้เธรดเด็กเสร็จสมบูรณ์และได้รับผลลัพธ์ของเธรดลูกก่อนที่จะดำเนินการต่อไป ในเวลานี้คุณสามารถใช้วิธีการเข้าร่วม
เธรด t1 = เธรดใหม่ (ใหม่ runnable () {@Override โมฆะสาธารณะ run () {long t = system.currentTimeMillis (); system.out.println (thread.currentthread (). getName ()+"เริ่มต้น"); ลอง {thread.sleep (1000) E.PrintStackTrace (); t1.start (); t1.join (); System.out.println ("รอให้ T1 ถูกดำเนินการก่อนดำเนินการ");ผลการดำเนินการ:
เธรด -0 startthread-0 t1 end 1001 รอให้ T1 ดำเนินการก่อนที่จะดำเนินการ
สรุป
ข้างต้นเป็นคำอธิบายโดยละเอียดทั้งหมดของรหัสวิธีการใช้งานของรหัสหลายเธรด Java ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น