เก็บขยะ

คอลเลกชัน Java
ระดับ , บทเรียน
มีอยู่

"สวัสดี! ฉันตัดสินใจที่จะให้บทเรียนเล็ก ๆ น้อย ๆ เกี่ยวกับการเก็บขยะแก่คุณอีกครั้ง"

ดังที่คุณทราบแล้วว่าเครื่อง Java จะตรวจสอบเมื่อวัตถุไม่จำเป็นและลบออก

“ใช่ คุณกับฤๅษีบอกฉันก่อนหน้านี้แล้ว ฉันจำรายละเอียดไม่ได้”

“โอเค งั้นเรามาทบทวนกันอีกครั้ง”

การเก็บขยะ - 1

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

"บอกฉันเล็กน้อยเกี่ยวกับคนเก็บขยะ - มันคืออะไรและทำงานอย่างไร"

"ตกลงการรวบรวมขยะเคยเกิดขึ้นในเธรดหลัก ทุก 5 นาทีหรือบ่อยกว่านั้น หากมีหน่วยความจำว่างไม่เพียงพอ เครื่อง Java จะระงับเธรดทั้งหมดและลบอ็อบเจ็กต์ที่ไม่ได้ใช้"

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

"ฉันเข้าใจแล้ว การตัดสินใจว่าจะลบวัตถุหรือไม่ทำเป็นอย่างไรกันแน่"

"การนับจำนวนการอ้างอิงถึงวัตถุนั้นไม่ได้ผลมากนัก อาจมีวัตถุที่อ้างอิงถึงกัน แต่ไม่มีวัตถุอื่นอ้างอิง"

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

"ตกลง ฉันคิดว่าฉันเข้าใจแล้ว"

"การรวบรวมขยะจริงเกิดขึ้นได้อย่างไร - การลบวัตถุที่ไม่จำเป็น"

"มันง่ายมาก ใน Java หน่วยความจำถูกแบ่งออกเป็นสองส่วนตามแบบแผน และเมื่อถึงเวลาสำหรับการรวบรวมขยะ อ็อบเจ็กต์ที่มีชีวิต (เข้าถึงได้) ทั้งหมดจะถูกคัดลอกไปยังอีกส่วนหนึ่งของหน่วยความจำ และหน่วยความจำเก่าจะถูกรีลีสทั้งหมด"

"นั่นเป็นวิธีการที่น่าสนใจ ไม่จำเป็นต้องนับการอ้างอิง: คัดลอกออบเจกต์ที่เข้าถึงได้ทั้งหมด และอย่างอื่นที่เหลือคือขยะ"

"มันซับซ้อนกว่านั้นเล็กน้อย โปรแกรมเมอร์ Java พบว่าออบเจกต์มักจะแบ่งออกเป็นสองประเภท: อายุยืน (ซึ่งมีอยู่ตลอดเวลาที่โปรแกรมทำงาน) และอายุสั้น (ซึ่งจำเป็นในวิธีการและสำหรับการดำเนินการ «โลคอล » การดำเนินงาน)"

"การแยกวัตถุที่มีอายุยืนยาวออกจากวัตถุที่มีอายุสั้นจะมีประสิทธิภาพมากกว่ามาก ในการทำเช่นนี้ จำเป็นต้องหาวิธีกำหนดอายุยืนของวัตถุ"

"ดังนั้น พวกเขาจึงแบ่งหน่วยความจำทั้งหมดออกเป็น «รุ่น» มีวัตถุรุ่นแรก วัตถุรุ่นที่สอง ฯลฯ ทุกครั้งที่หน่วยความจำถูกล้าง ตัวนับการสร้างจะเพิ่มขึ้น 1 ถ้าวัตถุบางอย่างอยู่ในหลายชั่วอายุคน ถูกบันทึกไว้ว่ามีอายุยืน"

"ทุกวันนี้ ตัวรวบรวมขยะเป็นส่วนที่ซับซ้อนและมีประสิทธิภาพมากของ Java หลายส่วนของมันทำงานแบบฮิวริสติก โดยอิงตามอัลกอริทึมที่คาดเดาได้ ผลก็คือ มัก «ไม่ฟัง» ผู้ใช้"

"ความหมาย?"

"Java มีวัตถุตัวรวบรวมขยะ ( GC ) ที่สามารถเรียกใช้ได้โดยใช้ เมธอด System.gc ()"

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

"โอ้โห! น่ารู้"

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

"และดูสิ Java มีการอ้างอิงพิเศษที่ให้คุณมีอิทธิพลต่อกระบวนการนี้ มีคลาส wrapper พิเศษสำหรับพวกเขา นี่คือ:"

" SoftReference  เป็นการอ้างอิงที่นุ่มนวล"

" WeakReference  คือการอ้างอิงที่อ่อนแอ"

" PhantomReferenceเป็นข้อมูลอ้างอิงแฝง"

"เอ่อ... นี่ทำให้ฉันนึกถึงคลาสภายใน คลาสที่ซ้อนกัน คลาสนิรนามที่ซ้อนกัน และคลาสโลคัล ชื่อต่างกัน แต่ยังไม่ชัดเจนว่ามีไว้เพื่ออะไร"

"พูดว่า Amigo คุณได้กลายเป็นโปรแกรมเมอร์แล้ว ตอนนี้คุณโกรธเพราะชื่อคลาส โดยพูดว่า «ไม่มีข้อมูลเพียงพอ และเป็นไปไม่ได้ด้วยชื่อเดียว (!) ที่จะตัดสินว่าคลาสนี้ทำอะไร อย่างไร และทำไม"."

"ว้าว ฉันไม่ได้สังเกตเลย แต่มันชัดเจนมาก"

"ตกลง พอแล้ว ให้ฉันบอกคุณเกี่ยวกับ SoftReferences"

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

"นี่คือตัวอย่างการอ้างอิงดังกล่าว:"

ตัวอย่าง
// Create a Cat object
Cat cat = new Cat();

// Create a soft reference to a Cat object
SoftReference<Cat> catRef = new SoftReference<Cat>(cat);

// Now only the catRef soft reference points at the object
cat = null;

// Now the ordinary cat variable also references the object
cat = catRef.get();

// Clear the soft reference
catRef.clear();

"หากเพียงการอ้างอิงถึงวัตถุอย่างนุ่มนวล มันก็ยังคงมีชีวิตต่อไป และเรียกว่า 'เข้าถึงได้อย่างนุ่มนวล'"

"แต่!  ตัวรวบรวมขยะสามารถลบวัตถุที่อ้างถึงโดยการอ้างอิงแบบซอฟต์เท่านั้นหากโปรแกรมมีหน่วยความจำไม่เพียงพอ  หากจู่ๆ โปรแกรมมีหน่วยความจำไม่เพียงพอ ก่อนที่จะโยนOutOfMemoryExceptionตัวรวบรวมขยะจะลบวัตถุทั้งหมด อ้างอิงโดย soft references และจะพยายามจัดสรรหน่วยความจำให้กับโปรแกรมอีกครั้ง"

"สมมติว่าโปรแกรมไคลเอ็นต์ร้องขอข้อมูลต่างๆ จากโปรแกรมเซิร์ฟเวอร์บ่อยๆ โปรแกรมเซิร์ฟเวอร์สามารถใช้ SoftReference เพื่อแคชข้อมูลบางส่วนได้ หากวัตถุที่เก็บไว้ไม่ให้ตายโดยการอ้างอิงแบบซอฟต์ใช้พื้นที่ส่วนใหญ่ของหน่วยความจำ จากนั้นตัวเก็บขยะก็จะลบออก ทั้งหมด มันสวย!"

"ใช่ ฉันชอบมันเอง"

"การเพิ่มเติมเล็กน้อย: คลาส SoftReferenceมีสองเมธอด เมธอด get() ส่งคืนวัตถุที่อ้างอิงโดย SoftReference หากวัตถุถูกลบโดยตัวเก็บขยะเมธอด get () จะเริ่มคืนค่า null ในทันที"

"ผู้ใช้ยังสามารถล้างข้อมูล SoftReferenceอย่างชัดเจนได้ด้วยการเรียกใช้เมธอด clear() ในกรณีนี้ ลิงก์ที่อ่อนแอภายใน วัตถุ SoftReferenceจะถูกทำลาย"

"นั่นคือทั้งหมดที่สำหรับตอนนี้."

"ขอบคุณสำหรับเรื่องราวที่น่าสนใจ เอลลี่ มันน่าสนใจมากจริงๆ"

ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION