การใช้ yield () หลักคืออะไรและแตกต่างจาก join () และ interrupt () อย่างไร?


106

ฉันสับสนเล็กน้อยเกี่ยวกับการใช้yield()วิธีการใน Java โดยเฉพาะในโค้ดตัวอย่างด้านล่าง ฉันยังอ่านว่า yield () คือ 'ใช้เพื่อป้องกันการดำเนินการของเธรด'

คำถามของฉันคือ:

  1. ฉันเชื่อว่าโค้ดด้านล่างให้ผลลัพธ์เดียวกันทั้งเมื่อใช้yield()และเมื่อไม่ใช้งาน ถูกต้องหรือไม่

  2. ที่จริงแล้วการใช้งานหลักคือyield()อะไร?

  3. ในสิ่งที่วิธีคือyield()แตกต่างจากjoin()และinterrupt()วิธีการ?

ตัวอย่างรหัส:

public class MyRunnable implements Runnable {

   public static void main(String[] args) {
      Thread t = new Thread(new MyRunnable());
      t.start();

      for(int i=0; i<5; i++) {
          System.out.println("Inside main");
      }
   }

   public void run() {
      for(int i=0; i<5; i++) {
          System.out.println("Inside run");
          Thread.yield();
      }
   }
}

ฉันได้รับผลลัพธ์เดียวกันโดยใช้รหัสด้านบนทั้งที่มีและไม่ใช้yield():

Inside main
Inside main
Inside main
Inside main
Inside main
Inside run
Inside run
Inside run
Inside run
Inside run

qustion นี้ควรจะปิดสำหรับการเป็นกว้างเกินไป
Raedwald

ไม่มันจะไม่ส่งคืนผลลัพธ์เดียวกันเมื่อคุณมีyield()และไม่ได้ เมื่อคุณมี i ขนาดใหญ่มากกว่า 5 คุณจะเห็นผลของyield()วิธีการ
lakshman

คำตอบ:


97

ที่มา: http://www.javamex.com/tutorials/threads/yield.shtml

Windows

ในการใช้งาน Hotspot วิธีการThread.yield()ทำงานได้เปลี่ยนไประหว่าง Java 5 และ Java 6

ใน Java 5 เรียกโทรThread.yield() API ของ Windows Sleep(0)นี้จะมีผลพิเศษของการล้างควอนตัมด้ายปัจจุบันและวางไปยังจุดสิ้นสุดของคิวสำหรับระดับความสำคัญ กล่าวอีกนัยหนึ่งเธรดที่รันได้ทั้งหมดที่มีลำดับความสำคัญเท่ากัน (และเธรดที่มีลำดับความสำคัญมากกว่า) จะได้รับโอกาสในการรันก่อนที่เธรดที่ให้ผลจะได้รับเวลา CPU ในครั้งถัดไป เมื่อมีการกำหนดเวลาใหม่ในที่สุดมันจะกลับมาพร้อมกับควอนตัมเต็มรูปแบบแต่ไม่ได้ "ทับ" ควอนตัมที่เหลือจากช่วงเวลาแห่งการยอมจำนน พฤติกรรมนี้แตกต่างเล็กน้อยจากการนอนหลับที่ไม่เป็นศูนย์โดยทั่วไปด้ายการนอนหลับจะสูญเสียค่าควอนตัม 1 ค่า (มีผลบังคับใช้ 1 ใน 3 ของขีด 10 หรือ 15 มิลลิวินาที)

ใน Java 6 พฤติกรรมนี้มีการเปลี่ยนแปลง ขณะนี้ Hotspot VM ดำเนินการ Thread.yield()โดยใช้การSwitchToThread()เรียกWindows API การเรียกนี้ทำให้เธรดปัจจุบันยกเลิกไทม์สไลซ์ปัจจุบันแต่ไม่ใช่ควอนตัมทั้งหมด ซึ่งหมายความว่าขึ้นอยู่กับลำดับความสำคัญของหัวข้ออื่น ๆ ที่ยอมด้ายสามารถกำหนดเวลากลับไปในช่วงเวลาต่อมาขัดจังหวะหนึ่ง (ดูหัวข้อการตั้งเวลาเธรดสำหรับข้อมูลเพิ่มเติมเกี่ยวกับช่วงเวลา)

ลินุกซ์

ภายใต้ Linux, Hotspot sched_yield()ก็เรียก ผลที่ตามมาของการโทรนี้แตกต่างกันเล็กน้อยและอาจรุนแรงกว่าใน Windows:

  • ด้ายยอมแพ้จะไม่ได้รับส่วนแบ่งของ CPU อีกจนกว่าทุกหัวข้ออื่น ๆ ที่มีส่วนแบ่งของซีพียู ;
  • (อย่างน้อยในเคอร์เนล 2.6.8 เป็นต้นไป) ความจริงที่ว่าเธรดได้รับผลจะถูกนำมาพิจารณาโดยปริยายโดยฮิวริสติกของตัวกำหนดตารางเวลาเกี่ยวกับการจัดสรร CPU ล่าสุด - โดยปริยายเธรดที่ให้ผลอาจได้รับ CPU มากขึ้นเมื่อกำหนดเวลาใน อนาคต.

(ดูหัวข้อการตั้งเวลาเธรดสำหรับรายละเอียดเพิ่มเติมเกี่ยวกับลำดับความสำคัญและอัลกอริทึมการตั้งเวลา)

ใช้เมื่อไหร่yield()?

ผมจะบอกว่าไม่เคย พฤติกรรมของมันไม่ได้กำหนดไว้ตามมาตรฐานและโดยทั่วไปมีวิธีที่ดีกว่าในการทำงานที่คุณอาจต้องการดำเนินการด้วย yield ():

  • ถ้าคุณกำลังพยายามที่จะใช้เพียงส่วนหนึ่งของ CPU ที่คุณสามารถทำเช่นนี้ในทางที่ควบคุมได้มากขึ้นโดยประเมินว่า CPU ด้ายได้ใช้ในก้อนสุดท้ายของการประมวลผลแล้วนอนหลับสำหรับระยะเวลาในการชดเชยบางส่วน: ดู วิธีการนอนหลับ () ;
  • หากคุณกำลังรอให้กระบวนการหรือทรัพยากรดำเนินการให้เสร็จสมบูรณ์หรือพร้อมใช้งานมีวิธีที่มีประสิทธิภาพมากขึ้นในการดำเนินการนี้เช่นการใช้join ()เพื่อรอให้เธรดอื่นเสร็จสมบูรณ์โดยใช้กลไกwait / alertเพื่ออนุญาตให้มีเธรดเดียว สัญญาณไปยังอีกที่งานเสร็จสมบูรณ์หรือความนึกคิดโดยใช้หนึ่งของ Java 5 เห็นพ้องสร้างเช่นสัญญาณหรือคิวการปิดกั้น

18
"ควอนตัมที่เหลือ", "ควอนตัมทั้งหมด" - บางคนลืมไปแล้วว่าคำว่า "ควอนตัม" หมายถึงอะไร
kbolino

@kbolino Quantum เป็นอะตอมใหม่
Evgeni Sergeev

2
@kbolino - ... latin: "เท่า", "เท่าไหร่" . ฉันไม่เห็นว่าสิ่งนี้ขัดแย้งกับการใช้งานข้างต้นอย่างไร คำนี้หมายถึงจำนวนที่อธิบายไว้เท่านั้นดังนั้นการแบ่งออกเป็นส่วนที่ใช้และส่วนที่เหลือจึงดูสมเหตุสมผลสำหรับฉัน
Periata Breatta

@PeriataBreatta ฉันคิดว่ามันสมเหตุสมผลกว่าถ้าคุณคุ้นเคยกับคำที่อยู่นอกฟิสิกส์ นิยามฟิสิกส์เป็นคำเดียวที่ฉันรู้
kbolino

ฉันให้ความสำคัญกับคำถามนี้เพื่อให้คำตอบนี้อัปเดตสำหรับ 7, 8, 9 แก้ไขด้วยข้อมูลปัจจุบันเกี่ยวกับ 7,8 และ 8 และคุณจะได้รับรางวัล

40

ฉันเห็นว่าคำถามถูกเปิดใช้งานอีกครั้งด้วยค่าหัวตอนนี้ถามว่าการใช้งานจริงyieldคืออะไร ฉันจะยกตัวอย่างจากประสบการณ์ของฉัน

อย่างที่เราทราบกันดีว่าการyieldบังคับให้เธรดการเรียกต้องยกเลิกโปรเซสเซอร์ที่รันอยู่เพื่อให้เธรดอื่นถูกกำหนดเวลาให้ทำงาน สิ่งนี้มีประโยชน์เมื่อเธรดปัจจุบันทำงานเสร็จในตอนนี้ แต่ต้องการกลับไปที่หน้าคิวอย่างรวดเร็วและตรวจสอบว่าเงื่อนไขบางอย่างมีการเปลี่ยนแปลงหรือไม่ สิ่งนี้แตกต่างจากตัวแปรเงื่อนไขอย่างไร? yieldช่วยให้เธรดกลับสู่สถานะรันได้เร็วขึ้นมาก เมื่อรอตัวแปรเงื่อนไขเธรดจะถูกระงับและต้องรอให้เธรดอื่นส่งสัญญาณว่าควรดำเนินการต่อyieldโดยพื้นฐานแล้วจะบอกว่า "อนุญาตให้เธรดอื่นทำงานได้ แต่อนุญาตให้ฉันกลับไปทำงานได้โดยเร็วที่สุดเพราะฉันคาดว่าจะมีอะไรเปลี่ยนแปลงในสถานะของฉันอย่างรวดเร็ว" สิ่งนี้บ่งบอกถึงการหมุนไม่ว่างซึ่งเงื่อนไขสามารถเปลี่ยนแปลงได้อย่างรวดเร็ว แต่การระงับเธรดจะทำให้ได้รับผลกระทบอย่างมาก

แต่พูดพล่ามพอสมควรนี่คือตัวอย่างที่เป็นรูปธรรม: รูปแบบขนานหน้าคลื่น ตัวอย่างพื้นฐานของปัญหานี้คือการคำนวณ "เกาะ" แต่ละตัวของ 1s ในอาร์เรย์แบบสองมิติที่เต็มไปด้วย 0 และ 1 "เกาะ" คือกลุ่มของเซลล์ที่อยู่ติดกันทั้งในแนวตั้งหรือแนวนอน:

1 0 0 0
1 1 0 0
0 0 0 1
0 0 1 1
0 0 1 1

ที่นี่เรามีเกาะ 1 เกาะ 2 เกาะ ได้แก่ บนซ้ายและขวาล่าง

วิธีแก้ปัญหาง่ายๆคือทำการส่งผ่านอาร์เรย์ทั้งหมดก่อนและแทนที่ค่า 1 ด้วยตัวนับที่เพิ่มขึ้นซึ่งในตอนท้ายแต่ละ 1 จะถูกแทนที่ด้วยหมายเลขลำดับตามลำดับหลักของแถว:

1 0 0 0
2 3 0 0
0 0 0 4
0 0 5 6
0 0 7 8

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

1 0 0 0
1 1 0 0
0 0 0 4
0 0 4 4
0 0 4 4

ตอนนี้เราสามารถระบุได้อย่างง่ายดายว่าเรามีเกาะสองเกาะ

ส่วนที่เราต้องการเรียกใช้แบบขนานคือขั้นตอนที่เราคำนวณค่าต่ำสุด โดยไม่ต้องลงรายละเอียดมากเกินไปแต่ละเธรดจะได้รับแถวในลักษณะที่แทรกสลับกันและอาศัยค่าที่คำนวณโดยการประมวลผลเธรดในแถวด้านบน ดังนั้นแต่ละเธรดจึงต้องล้าหลังเล็กน้อยในการประมวลผลเธรดในบรรทัดก่อนหน้า แต่ก็ต้องดำเนินการให้ทันภายในเวลาที่เหมาะสม รายละเอียดเพิ่มเติมและการนำไปใช้งานได้แสดงไว้ในเอกสารนี้ หมายเหตุการใช้งานของซึ่งจะมากหรือน้อยเทียบเท่าซีsleep(0)yield

ในกรณีนี้yieldถูกใช้เพื่อบังคับให้แต่ละเธรดหยุดชั่วคราว แต่เนื่องจากการประมวลผลเธรดแถวที่อยู่ติดกันจะเลื่อนไปอย่างรวดเร็วในระหว่างนี้ตัวแปรเงื่อนไขจึงเป็นตัวเลือกที่หายนะ

อย่างที่คุณเห็นyieldเป็นการเพิ่มประสิทธิภาพแบบละเอียด การใช้งานในสถานที่ที่ไม่ถูกต้องเช่นการรอในสภาพที่ไม่ค่อยเปลี่ยนแปลงจะทำให้เกิดการใช้งาน CPU มากเกินไป

ขออภัยสำหรับการพูดพล่ามยาวหวังว่าฉันจะทำให้ตัวเองชัดเจน


1
IIUC สิ่งที่คุณนำเสนอในเอกสารแนวคิดก็คือในกรณีนี้การรอไม่ว่างจะมีประสิทธิภาพมากกว่าการโทรyieldเมื่อเงื่อนไขไม่เป็นที่พอใจเพื่อให้เธรดอื่นมีโอกาสดำเนินการคำนวณแทนการใช้สูงกว่า การประสานระดับดั้งเดิมใช่ไหม?
Petr Pudlák

3
@Petr Pudlák: ครับ ฉันเปรียบเทียบสิ่งนี้กับการใช้การส่งสัญญาณเธรดและความแตกต่างของประสิทธิภาพเป็นอย่างมากในกรณีนี้ เนื่องจากเงื่อนไขที่สามารถกลายเป็นจริงได้อย่างรวดเร็ว (นี้เป็นปัญหาสำคัญ) ตัวแปรสภาพจะช้าเกินไปที่ด้ายจะถูกพักไว้โดย OS มากกว่าให้ขึ้น CPU yieldสำหรับระยะเวลาที่สั้นมากใช้
ทิวดอร์

@ นักเรียนคำอธิบายที่ดี!
พัฒนา Marius Žilėnas

1
"สังเกตการใช้สลีป (0) ซึ่งมากกว่าหรือน้อยกว่าผลตอบแทนที่เทียบเท่าของ C" .. ถ้าคุณต้องการ sleep (0) กับ java ทำไมคุณไม่ใช้แค่นั้นล่ะ Thread.sleep () เป็นสิ่งที่มีอยู่แล้ว ฉันไม่แน่ใจว่าคำตอบนี้ให้เหตุผลว่าทำไมจึงใช้ Thread.yield () แทน Thread.sleep (0); นอกจากนี้ยังมีเธรดที่มีอยู่เพื่ออธิบายว่าเหตุใดจึงแตกต่างกัน
eis

@eis: Thread.sleep (0) vs Thread.yield () อยู่นอกเหนือขอบเขตของคำตอบนี้ ฉันแค่พูดถึง Thread.sleep (0) สำหรับคนที่กำลังมองหาค่าใกล้เคียงกันใน C. คำถามเกี่ยวกับการใช้ Thread.yield ()
ทิวดอร์

12

เกี่ยวกับความแตกต่างระหว่างyield(), interrupt()และjoin()- โดยทั่วไปไม่เพียง แต่ใน Java:

  1. การยอมจำนน : แท้จริงแล้วการ 'ยอมจำนน' หมายถึงการปล่อยวางยอมแพ้ยอมจำนน เธรดที่ให้ผลจะบอกระบบปฏิบัติการ (หรือเครื่องเสมือนหรืออะไรก็ตาม) ว่ายินดีที่จะให้เธรดอื่นได้รับการจัดกำหนดการแทน สิ่งนี้บ่งชี้ว่ามันไม่ได้ทำอะไรที่สำคัญเกินไป เป็นเพียงคำใบ้เท่านั้นและไม่รับประกันว่าจะมีผลกระทบใด ๆ
  2. การเข้าร่วม : เมื่อหลายเธรด 'เข้าร่วม' บนแฮนเดิลหรือโทเค็นหรือเอนทิตีทั้งหมดจะรอจนกว่าเธรดที่เกี่ยวข้องอื่น ๆ ทั้งหมดจะเสร็จสิ้นการดำเนินการ (ทั้งหมดหรือไม่เกินการรวมที่เกี่ยวข้องของตนเอง) นั่นหมายความว่าเธรดหลายชุดทำงานเสร็จเรียบร้อยแล้ว จากนั้นแต่ละเธรดเหล่านี้สามารถกำหนดเวลาให้ทำงานอื่น ๆ ต่อได้โดยสามารถถือว่างานทั้งหมดนั้นเสร็จสมบูรณ์แล้ว (เพื่อไม่ให้สับสนกับ SQL Joins!)
  3. การขัดจังหวะ : ใช้โดยเธรดหนึ่งเพื่อ 'โผล่' เธรดอื่นซึ่งกำลังนอนหลับหรือกำลังรอหรือเข้าร่วม - เพื่อให้มีการกำหนดเวลาให้ทำงานต่อไปอีกครั้งอาจมีข้อบ่งชี้ว่าถูกขัดจังหวะ (เพื่อไม่ให้สับสนกับฮาร์ดแวร์ขัดจังหวะ!)

สำหรับ Java โดยเฉพาะโปรดดู

  1. เข้าร่วม:

    วิธีใช้ Thread.join? (ที่นี่ใน StackOverflow)

    เข้าร่วมกระทู้เมื่อใด

  2. ผลตอบแทน:

  3. ขัดจังหวะ:

    Thread.interrupt () ชั่วร้ายหรือไม่? (ที่นี่ใน StackOverflow)


การเข้าร่วมแฮนเดิลหรือโทเค็นหมายความว่าอย่างไร วิธีการ wait () และการแจ้งเตือน () อยู่บน Object ทำให้ผู้ใช้สามารถรอ Object ใด ๆ ได้ แต่ join () ดูเหมือนนามธรรมน้อยกว่าและจำเป็นต้องเรียกใช้ Thread เฉพาะที่คุณต้องการทำให้เสร็จก่อนดำเนินการต่อ ... ใช่หรือไม่?
spaaarky21

@ spaaarky21: ฉันหมายถึงโดยทั่วไปไม่จำเป็นต้องเป็นภาษา Java นอกจากนี้ a wait()ไม่ใช่การเข้าร่วม แต่เกี่ยวกับการล็อควัตถุที่เธรดการเรียกกำลังพยายามที่จะได้มาซึ่งจะรอจนกว่าการล็อกจะถูกปลดปล่อยโดยผู้อื่นและได้รับเธรด ปรับเปลี่ยนคำตอบของฉันตามนั้น
einpoklum

10

ประการแรกคำอธิบายที่แท้จริงคือ

ทำให้อ็อบเจ็กต์เธรดที่กำลังดำเนินการในปัจจุบันหยุดชั่วคราวและอนุญาตให้เธรดอื่นดำเนินการ

ตอนนี้มีความเป็นไปได้สูงที่เธรดหลักของคุณจะดำเนินการวนซ้ำห้าครั้งก่อนที่runวิธีการของเธรดใหม่จะถูกเรียกใช้ดังนั้นการเรียกทั้งหมดyieldจะเกิดขึ้นหลังจากที่ดำเนินการวนซ้ำในเธรดหลักแล้วเท่านั้น

joinจะหยุดเธรดปัจจุบันจนกว่าเธรดที่ถูกเรียกด้วยjoin()จะเสร็จสิ้น

interruptจะขัดจังหวะด้ายมันจะถูกเรียกว่าก่อให้เกิดInterruptedException

yield อนุญาตให้สลับบริบทไปยังเธรดอื่นดังนั้นเธรดนี้จะไม่ใช้การใช้งาน CPU ทั้งหมดของกระบวนการ


+1. โปรดทราบว่าหลังจากเรียก yield () แล้วยังไม่มีการรับประกันว่าเธรดเดียวกันจะไม่ถูกเลือกสำหรับการดำเนินการอีกครั้งโดยมีกลุ่มเธรดที่มีลำดับความสำคัญเท่ากัน
Andrew Fielden

อย่างไรก็ตามการ SwitchToThread()โทรดีกว่า Sleep (0) และนี่ควรเป็นข้อผิดพลาดใน Java :)
ПетърПетров

4

คำตอบปัจจุบันล้าสมัยและต้องมีการแก้ไขตามการเปลี่ยนแปลงล่าสุด

ไม่มีความแตกต่างในทางปฏิบัติThread.yield()ระหว่างเวอร์ชัน Java ตั้งแต่ 6 ถึง 9

TL; DR;

ข้อสรุปตามซอร์สโค้ด OpenJDK ( http://hg.openjdk.java.net/ )

หากไม่คำนึงถึงการสนับสนุน HotSpot ของโพรบ USDT (ข้อมูลการติดตามระบบอธิบายไว้ในคู่มือ dtrace ) และคุณสมบัติ JVM ConvertYieldToSleepซอร์สโค้ดของyield()เกือบจะเหมือนกัน ดูคำอธิบายด้านล่าง

Java 9 :

Thread.yield()เรียกวิธีการเฉพาะ OS os::naked_yield():
บน Linux:

void os::naked_yield() {
    sched_yield();
}

บน Windows:

void os::naked_yield() {
    SwitchToThread();
}

Java 8 และรุ่นก่อนหน้า:

Thread.yield()เรียกวิธีการเฉพาะ OS os::yield():
บน Linux:

void os::yield() {
    sched_yield();
}

บน Windows:

void os::yield() {  os::NakedYield(); }

อย่างที่คุณเห็นThread.yeald()บน Linux นั้นเหมือนกันสำหรับเวอร์ชัน Java ทั้งหมด
มาดู Windows os::NakedYield()จาก JDK 8:

os::YieldResult os::NakedYield() {
    // Use either SwitchToThread() or Sleep(0)
    // Consider passing back the return value from SwitchToThread().
    if (os::Kernel32Dll::SwitchToThreadAvailable()) {
        return SwitchToThread() ? os::YIELD_SWITCHED : os::YIELD_NONEREADY ;
    } else {
        Sleep(0);
    }
    return os::YIELD_UNKNOWN ;
}

ความแตกต่างระหว่าง Java 9 และ Java 8 ในการตรวจสอบเพิ่มเติมของการดำรงอยู่ของ Win32 API ของSwitchToThread()วิธีการ มีรหัสเดียวกันสำหรับ Java 6
ซอร์สโค้ดของos::NakedYield()ใน JDK 7 แตกต่างกันเล็กน้อย แต่มีลักษณะการทำงานเหมือนกัน:

    os::YieldResult os::NakedYield() {
    // Use either SwitchToThread() or Sleep(0)
    // Consider passing back the return value from SwitchToThread().
    // We use GetProcAddress() as ancient Win9X versions of windows doen't support SwitchToThread.
    // In that case we revert to Sleep(0).
    static volatile STTSignature stt = (STTSignature) 1 ;

    if (stt == ((STTSignature) 1)) {
        stt = (STTSignature) ::GetProcAddress (LoadLibrary ("Kernel32.dll"), "SwitchToThread") ;
        // It's OK if threads race during initialization as the operation above is idempotent.
    }
    if (stt != NULL) {
        return (*stt)() ? os::YIELD_SWITCHED : os::YIELD_NONEREADY ;
    } else {
        Sleep (0) ;
    }
    return os::YIELD_UNKNOWN ;
}

การตรวจสอบเพิ่มเติมถูกยกเลิกเนื่องจากSwitchToThread()วิธีการมีให้ตั้งแต่ Windows XP และ Windows Server 2003 (ดูหมายเหตุ msdn )


2

ความจริงแล้วการใช้ผลตอบแทนหลัก () คืออะไร?

Yield แนะนำให้ CPU ทราบว่าคุณอาจหยุดเธรดปัจจุบันและเริ่มดำเนินการเธรดที่มีลำดับความสำคัญสูงกว่า กล่าวอีกนัยหนึ่งคือการกำหนดค่าลำดับความสำคัญต่ำให้กับเธรดปัจจุบันเพื่อให้มีที่ว่างสำหรับเธรดที่สำคัญมากขึ้น

ฉันเชื่อว่าโค้ดด้านล่างให้ผลลัพธ์เดียวกันทั้งเมื่อใช้ yield () และเมื่อไม่ใช้ ถูกต้องหรือไม่

ไม่ทั้งสองจะให้ผลลัพธ์ที่แตกต่างกัน หากไม่มีผลตอบแทน () เมื่อเธรดได้รับการควบคุมมันจะดำเนินการลูป 'Inside run' ในครั้งเดียว อย่างไรก็ตามด้วย Yield () เมื่อเธรดได้รับการควบคุมมันจะพิมพ์ 'Inside run' หนึ่งครั้งจากนั้นจะส่งมอบการควบคุมไปยังเธรดอื่น ๆ หากมี หากไม่มีเธรดที่รอดำเนินการเธรดนี้จะกลับมาทำงานอีกครั้ง ดังนั้นทุกครั้งที่เรียกใช้ "Inside run" มันจะมองหาเธรดอื่น ๆ เพื่อดำเนินการและหากไม่มีเธรดอยู่เธรดปัจจุบันจะยังคงทำงานต่อไป

Yield () แตกต่างจากวิธี join () และ interrupt () อย่างไร?

Yield () มีไว้สำหรับการเพิ่มพื้นที่ให้กับเธรดที่สำคัญอื่น ๆ join () ใช้สำหรับรอให้เธรดอื่นดำเนินการให้เสร็จสิ้นและ interrupt () ใช้สำหรับการขัดจังหวะเธรดที่กำลังดำเนินการอยู่เพื่อทำอย่างอื่น


แค่อยากจะยืนยันว่าคำพูดนี้เป็นจริงWithout a yield(), once the thread gets control it will execute the 'Inside run' loop in one goหรือไม่? กรุณาชี้แจง.
Abdullah Khan

0

Thread.yield()ทำให้เธรดเปลี่ยนจากสถานะ "กำลังทำงาน" เป็นสถานะ "รันได้" หมายเหตุ: ไม่ทำให้เธรดเข้าสู่สถานะ "กำลังรอ"


@PJMeisch ไม่มีRUNNINGสถานะสำหรับjava.lang.Threadอินสแตนซ์ แต่นั่นไม่ได้กีดกันสถานะ "กำลังทำงาน" ดั้งเดิมสำหรับเธรดเนทีฟซึ่งThreadอินสแตนซ์เป็นพร็อกซี
Solomon Slow

-1

Thread.yield ()

เมื่อเราเรียกใช้เมธอด Thread.yield () ตัวกำหนดตารางเวลาเธรดจะเก็บเธรดที่กำลังรันอยู่ในสถานะ Runnable และเลือกเธรดอื่นที่มีลำดับความสำคัญเท่ากันหรือลำดับความสำคัญสูงกว่า หากไม่มีเธรดที่มีลำดับความสำคัญเท่ากันและสูงกว่าจะกำหนดเวลาการเรียกใช้เธรดอัตราผลตอบแทน () ใหม่ โปรดจำไว้ว่าวิธีการให้ผลตอบแทนไม่ได้ทำให้เธรดไปที่สถานะรอหรือถูกบล็อก สามารถสร้างเธรดจาก Running State เป็น Runnable State ได้เท่านั้น

เข้าร่วม ()

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


-4

Yield () การใช้งานหลักคือการพักแอปพลิเคชันมัลติเธรดไว้

ความแตกต่างของวิธีการเหล่านี้ทั้งหมดคือ yield () ทำให้เธรดถูกพักไว้ในขณะที่รันเธรดอื่นและย้อนกลับหลังจากเธรดนั้นเสร็จสิ้นแล้ว join () จะนำจุดเริ่มต้นของเธรดมารวมกันเพื่อดำเนินการจนจบและเธรดอื่นเพื่อรันหลังจากเธรดนั้นมี สิ้นสุดแล้ว interrupt () จะหยุดการทำงานของเธรดชั่วขณะหนึ่ง


ขอบคุณสำหรับคำตอบ. อย่างไรก็ตามเพียงแค่ทำซ้ำสิ่งที่คำตอบอื่นอธิบายรายละเอียดอยู่แล้ว ฉันเสนอเงินรางวัลสำหรับกรณีการใช้งานที่เหมาะสมที่yieldควรใช้
Petr Pudlák
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.