CodeGym /Java Blog /சீரற்ற /ஜாவாவில் பாண்டம் குறிப்புகள்
John Squirrels
நிலை 41
San Francisco

ஜாவாவில் பாண்டம் குறிப்புகள்

சீரற்ற குழுவில் வெளியிடப்பட்டது
வணக்கம்! இன்றைய விவாதத்தில், ஜாவாவில் "பாண்டம் குறிப்புகள்" (PhantomReference) பற்றி விரிவாகப் பேசுவோம். இவை என்ன வகையான குறிப்புகள்? அவை ஏன் "பாண்டம் குறிப்புகள்" என்று அழைக்கப்படுகின்றன? அவை எவ்வாறு பயன்படுத்தப்படுகின்றன? நீங்கள் நினைவில் வைத்திருப்பது போல், ஜாவாவில் 4 வகையான குறிப்புகள் உள்ளன:
  1. StrongReference (ஒரு பொருளை உருவாக்கும் போது நாம் உருவாக்கும் சாதாரண குறிப்புகள்):

    Cat cat = new Cat()

    இந்த எடுத்துக்காட்டில், பூனை ஒரு வலுவான குறிப்பு.

  2. Soft Reference (மென்மையான குறிப்பு). அத்தகைய குறிப்புகள் பற்றி எங்களுக்கு ஒரு பாடம் இருந்தது.

  3. பலவீனமான குறிப்பு (பலவீனமான குறிப்பு). அவர்களைப் பற்றிய பாடமும் இங்கே இருந்தது .

  4. பாண்டம் குறிப்பு (பாண்டம் குறிப்பு).

கடைசி மூன்று வகை அளவுருக்கள் கொண்ட பொதுவான வகைகள் (உதாரணமாக, SoftReference<Integer> , WeakReference<MyClass> ). SoftReference , WeakReference , மற்றும் PhantomReference வகுப்புகள் குறிப்பு வகுப்பிலிருந்து பெறப்படுகின்றன . இந்த வகுப்புகளுடன் பணிபுரியும் போது மிக முக்கியமான முறைகள்:
  • get() - குறிப்பிடப்பட்ட பொருளைத் தருகிறது;

  • clear() - பொருளின் குறிப்பை நீக்குகிறது.

SoftReference மற்றும் WeakReference பற்றிய பாடங்களில் இருந்து இந்த முறைகளை நீங்கள் நினைவில் வைத்திருக்கிறீர்கள் . வெவ்வேறு வகையான குறிப்புகளுடன் அவை வித்தியாசமாக செயல்படுகின்றன என்பதை நினைவில் கொள்வது அவசியம். இன்று நாம் முதல் மூன்று வகைகளுக்குள் நுழைய மாட்டோம். மாறாக, பாண்டம் குறிப்புகளைப் பற்றி பேசுவோம். மற்ற வகை குறிப்புகளை நாங்கள் தொடுவோம், ஆனால் அவை பாண்டம் குறிப்புகளிலிருந்து எவ்வாறு வேறுபடுகின்றன என்பதைப் பொறுத்து மட்டுமே. போகலாம்! :) தொடங்குவதற்கு, நமக்கு ஏன் பாண்டம் குறிப்புகள் தேவை? உங்களுக்குத் தெரியும், குப்பை சேகரிப்பான் (ஜிசி) தேவையற்ற ஜாவா பொருள்களால் பயன்படுத்தப்படும் நினைவகத்தை வெளியிடுகிறது. சேகரிப்பான் ஒரு பொருளை இரண்டு "பாஸ்களில்" நீக்குகிறது. முதல் பாஸில், அது பொருட்களை மட்டுமே பார்க்கிறது, தேவைப்பட்டால், அவற்றை "தேவையற்றது" (அதாவது, "நீக்கப்பட வேண்டும்") எனக் குறிக்கும். என்றால்finalize()பொருளுக்கு முறை மேலெழுதப்பட்டது, அது அழைக்கப்படுகிறது. அல்லது ஒருவேளை அது அழைக்கப்படாமல் இருக்கலாம் - இவை அனைத்தும் நீங்கள் அதிர்ஷ்டசாலி என்பதை மட்டுமே சார்ந்துள்ளது. அது நிலையற்றது என்பது உங்களுக்கு நினைவிருக்கலாம் finalize():) குப்பை சேகரிப்பாளரின் இரண்டாவது பாஸில், பொருள் நீக்கப்பட்டது மற்றும் நினைவகம் விடுவிக்கப்பட்டது. குப்பை சேகரிப்பவரின் எதிர்பாராத நடத்தை நமக்கு பல பிரச்சனைகளை உருவாக்குகிறது. குப்பை சேகரிக்கும் இயந்திரம் எப்போது இயங்கத் தொடங்கும் என்று எங்களுக்குத் தெரியாது. finalize()முறை அழைக்கப்படுமா என்பது எங்களுக்குத் தெரியாது . கூடுதலாக, ஒரு பொருளின் முறை செயல்படுத்தப்படும் போது அதன் வலுவான குறிப்பை உருவாக்க முடியும் finalize(), இந்த விஷயத்தில் பொருள் நீக்கப்படாது. கிடைக்கக்கூடிய நினைவகத்தில் அதிக கோரிக்கைகளை வைக்கும் நிரல்களுக்கு, இது எளிதாக ஒரு OutOfMemoryError. இவை அனைத்தும் பாண்டம் குறிப்புகளைப் பயன்படுத்த நம்மைத் தள்ளுகின்றன. இது குப்பை சேகரிப்பவரின் நடத்தையை மாற்றுகிறது என்பதே உண்மை. பொருளில் பாண்டம் குறிப்புகள் மட்டுமே இருந்தால், பின்:
  • அதன் இறுதி () முறை அழைக்கப்படுகிறது (அது மேலெழுதப்பட்டால்)

  • ஃபைனலைஸ்() முறை முடிந்ததும் எதுவும் மாறவில்லை என்றால் , அப்ஜெக்ட் இன்னும் நீக்கப்படலாம் என்றால், பொருளின் பாண்டம் குறிப்பு ஒரு சிறப்பு வரிசையில் வைக்கப்படும்: ReferenceQueue .

பாண்டம் குறிப்புகளுடன் பணிபுரியும் போது புரிந்து கொள்ள வேண்டிய மிக முக்கியமான விஷயம் என்னவென்றால், இந்த வரிசையில் அதன் பாண்டம் குறிப்பு இருக்கும் வரை பொருள் நினைவகத்திலிருந்து நீக்கப்படாது. பாண்டம் குறிப்பில் தெளிவான() முறை அழைக்கப்பட்ட பின்னரே அது நீக்கப்படும் . ஒரு உதாரணத்தைப் பார்ப்போம். முதலில், சில வகையான தரவைச் சேமிக்கும் ஒரு சோதனை வகுப்பை உருவாக்குவோம்.

public class TestClass {
   private StringBuffer data;
   public TestClass() {
       this.data = new StringBuffer();
       for (long i = 0; i < 50000000; i++) {
           this.data.append('x');
       }
   }
   @Override
   protected void finalize() {
       System.out.println("The finalize method has been called on the TestClass object");
   }
}
நாம் பொருட்களை உருவாக்கும் போது, ​​அதிக நினைவகத்தை எடுத்துக்கொள்வதற்காக, வேண்டுமென்றே அதிக "சுமை" (ஒவ்வொரு பொருளுக்கும் 50 மில்லியன் "x" எழுத்துக்களைச் சேர்ப்பதன் மூலம்) கொடுப்போம். கூடுதலாக, அது இயங்குவதைப் பார்க்க இறுதி() முறையை மேலெழுதுகிறோம். அடுத்து, PhantomReference இலிருந்து பெறப்படும் ஒரு வகுப்பு நமக்குத் தேவை . எங்களுக்கு ஏன் அத்தகைய வகுப்பு தேவை? இது எல்லாம் நேரடியானது. பாண்டம் குறிப்பு உண்மையில் அழிக்கப்பட்டதா என்பதைச் சரிபார்க்க இது தெளிவான() முறையில் கூடுதல் தர்க்கத்தைச் சேர்க்க அனுமதிக்கும் (அதாவது பொருள் நீக்கப்பட்டுவிட்டது).

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;

public class MyPhantomReference<TestClass> extends PhantomReference<TestClass> {

   public MyPhantomReference(TestClass obj, ReferenceQueue<TestClass> queue) {

       super(obj, queue);

       Thread thread = new QueueReadingThread<TestClass>(queue);

       thread.start();
   }

   public void cleanup() {
       System.out.println("Cleaning up a phantom reference! Removing an object from memory!");
       clear();
   }
}
அடுத்து, குப்பை சேகரிப்பவர் தனது வேலையைச் செய்யக் காத்திருக்கும் ஒரு தனி நூல் தேவை, மேலும் மறைமுக இணைப்புகள் எங்கள் ReferenceQueue இல் தோன்றும் . அத்தகைய குறிப்பு வரிசையில் முடிவடைந்தவுடன், சுத்தம் செய்யும் () முறை அதில் அழைக்கப்படுகிறது:

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;

public class QueueReadingThread<TestClass> extends Thread {

   private ReferenceQueue<TestClass> referenceQueue;

   public QueueReadingThread(ReferenceQueue<TestClass> referenceQueue) {
       this.referenceQueue = referenceQueue;
   }

   @Override
   public void run() {

       System.out.println("The thread monitoring the queue has started!");
       Reference ref = null;

       // Wait until the references appear in the queue
       while ((ref = referenceQueue.poll()) == null) {

           try {
               Thread.sleep(50);
           }

           catch (InterruptedException e) {
               throw new RuntimeException("Thread " + getName() + " was interrupted!");
           }
       }

       // As soon as a phantom reference appears in the queue, clean it up
       ((MyPhantomReference) ref).cleanup();
   }
}
இறுதியாக, எங்களுக்கு மெயின்() முறை தேவை, அதை தனி முதன்மை வகுப்பில் வைப்போம் . அந்த முறையில், நாங்கள் ஒரு TestClass ஆப்ஜெக்ட், அதற்கு ஒரு பாண்டம் குறிப்பு மற்றும் பாண்டம் குறிப்புகளுக்கான வரிசையை உருவாக்குவோம் . அதன் பிறகு, குப்பை சேகரிப்பாளரை அழைத்து என்ன நடக்கிறது என்று பார்ப்போம் :)

import java.lang.ref.*;

public class Main {

   public static void main(String[] args) throws InterruptedException {
       Thread.sleep(10000);

       ReferenceQueue<TestClass> queue = new ReferenceQueue<>();
       Reference ref = new MyPhantomReference<>(new TestClass(), queue);

       System.out.println("ref = " + ref);

       Thread.sleep(5000);

       System.out.println("Collecting garbage!");

       System.gc();
       Thread.sleep(300);

       System.out.println("ref = " + ref);

       Thread.sleep(5000);

       System.out.println("Collecting garbage!");

       System.gc();
   }
}
கன்சோல் வெளியீடு:

ref = MyPhantomReference@4554617c 
The thread monitoring the queue has started! 
Collecting garbage! 
The finalize method has been called on the TestClass object 
ref = MyPhantomReference@4554617c 
Collecting garbage! 
Cleaning up a phantom reference! 
Removing an object from memory! 
நாம் இங்கே என்ன பார்க்கிறோம்? நாங்கள் திட்டமிட்டபடி எல்லாம் நடந்தது! எங்கள் பொருளின் இறுதி() முறை மேலெழுதப்பட்டது மற்றும் குப்பை சேகரிப்பான் இயங்கும் போது அது அழைக்கப்பட்டது. அடுத்து, பாண்டம் குறிப்பு ReferenceQueue இல் வைக்கப்பட்டது . அங்கு இருக்கும் போது, ​​அதன் தெளிவான() முறை அழைக்கப்பட்டது (அதற்குள் கன்சோலுக்கு அவுட்புட் செய்ய க்ளீனப்() என்று அழைத்தோம்). இறுதியாக, பொருள் நினைவகத்திலிருந்து நீக்கப்பட்டது. இது எவ்வாறு செயல்படுகிறது என்பதை இப்போது நீங்கள் பார்க்கிறீர்கள் :) நிச்சயமாக, பாண்டம் குறிப்புகள் பற்றிய அனைத்து கோட்பாடுகளையும் நீங்கள் மனப்பாடம் செய்ய வேண்டியதில்லை. ஆனால் குறைந்த பட்சம் முக்கிய குறிப்புகளையாவது நினைவில் வைத்துக் கொண்டால் நல்லது. முதலாவதாக, இவை எல்லாவற்றிலும் பலவீனமான குறிப்புகள். பொருளைப் பற்றிய வேறு குறிப்புகள் எஞ்சியிருக்கும் போது மட்டுமே அவை செயல்பாட்டுக்கு வருகின்றன. மேலே நாம் கொடுத்த குறிப்புகளின் பட்டியல் வலுவற்றதில் இருந்து பலவீனமாக இறங்கு வரிசையில் வரிசைப்படுத்தப்பட்டுள்ளது: StrongReference -> SoftReference -> WeakReference -> PhantomReference நமது பொருளுக்கு வலுவான, மென்மையான அல்லது பலவீனமான குறிப்புகள் இல்லாதபோது மட்டுமே ஒரு மறைமுக குறிப்பு போரில் நுழைகிறது: ) இரண்டாவதாக, ஒரு பாண்டம் குறிப்புக்கு get() முறை எப்போதும் பூஜ்யமாக இருக்கும். மூன்று வெவ்வேறு வகையான கார்களுக்கு மூன்று வெவ்வேறு வகையான குறிப்புகளை உருவாக்கும் எளிய எடுத்துக்காட்டு இங்கே:

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       HybridAuto hybrid = new HybridAuto();
       F1Car f1car = new F1Car();

       SoftReference<Sedan> softReference = new SoftReference<>(sedan);
       System.out.println(softReference.get());

       WeakReference<HybridAuto> weakReference = new WeakReference<>(hybrid);
       System.out.println(weakReference.get());
      
       ReferenceQueue<F1Car> referenceQueue = new ReferenceQueue<>();

       PhantomReference<F1Car> phantomReference = new PhantomReference<>(f1car, referenceQueue);
       System.out.println(phantomReference.get());

   }
}
கன்சோல் வெளியீடு:

Sedan@4554617c
HybridAuto@74a14482 
null
Get () முறையானது மென்மையான மற்றும் பலவீனமான குறிப்புகளுக்கு முற்றிலும் சாதாரண பொருள்களை வழங்கியது, ஆனால் அது பாண்டம் குறிப்புக்கு பூஜ்யமாக திரும்பியது. மூன்றாவதாக, பாண்டம் குறிப்புகள் முக்கியமாக நினைவகத்திலிருந்து பொருட்களை நீக்குவதற்கான சிக்கலான நடைமுறைகளில் பயன்படுத்தப்படுகின்றன. அவ்வளவுதான்! :) இன்று நமது பாடம் முடிவடைகிறது. ஆனால் நீங்கள் கோட்பாட்டில் மட்டும் வெகுதூரம் செல்ல முடியாது, எனவே பணிகளைத் தீர்ப்பதற்குத் திரும்புவதற்கான நேரம் இது! :)
கருத்துக்கள்
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION