Solved

How to use reference queue with Hashtable objects?

Posted on 2003-12-05
16
746 Views
Last Modified: 2012-06-27
Assume I have a Hashtable, htobjects, and add WeakReference wrapped objects to it, such as:

htobjects.put(id, new wReference(value,refQueue));

Then in a thread I want to poll refQueue and if it contains weak references, I want to delete them from the Hashtable:

public void run() {
         while ( true ) {        
             Reference ref = refQueue.poll();  
              if ( ref == null )          
                 break;      
             htobjects.remove( ref );      
      //insert delay
      }
        }

The problem with run() is that ref is a reference to a value and not an ID/Key.  Any ideas what to do?

0
Comment
Question by:Taurus
  • 8
  • 5
  • 3
16 Comments
 
LVL 15

Expert Comment

by:jimmack
ID: 9887751
How important are your references to the fact that you're dealing with WeakReferences?  (Have you looked at java.util.WeakHashMap?)

If you are only interested in removing a value from a Hashtable, given a key, then you'll need to get the keys for the table and iterate through them to find the matching value(s).  You might also want to do a check with containsValue() first.
0
 

Author Comment

by:Taurus
ID: 9889088
Yes I know of Weak references.  I've attempted to keep this question succinct but since your comment elicits further info. on what I'm trying to accomplish, see the answer by objects in another of my posts:

http://www.experts-exchange.com/Programming/Programming_Languages/Java/Q_20783541.html

My Hashtables are shared references and I want to use this ref. queue idea.  If neccessary I thought about having the values stored in the Hashtable(s) contain their own keys.  However there seems to be a type mismatch issue to work around.  
0
 
LVL 15

Assisted Solution

by:jimmack
jimmack earned 30 total points
ID: 9890075
I've had a look at the question you referred to and the article that CEHJ referred to in it.  If I've understood correctly what you are now doing (with the use of ReferenceQueue etc.), then I now see your problem.  If the reference was the key in the Hashmap, then it would be deleted automatically, but since it's the value, this doesn't happen.

If this is the case, then I think that the value in the Hashtable is being nullified, but still exists (since the key still exists), so you need to iterate through the Hashmap keys and when a value for a key is null, remove the key.
0
 
LVL 92

Accepted Solution

by:
objects earned 70 total points
ID: 9891144
Not sure the polling idea is a good one for the reasons you have encountered, plus some thread synchronisation issues.
Any particular reason for wanting to remove them from your hashtable when they are cleared? Considering that the memory that you are concerned about has already been cleared, you could not worry about it and just remove them if accessed.
Perhaps creating a wrapper class to hide inards from the user of the class.

public class MyWeakMap
{
   private Hashtable Refs= new Hashtable();

   public void put(Object key, Object value)
   {
      Refs.put(key, new WeakReference(value));
   }

   public Object get(Object key)
   {
      WeakReference ref = () Refs.get(key);
      Object result = ref.get();
      if (result==null)
      {
         Refs.remove(key);
      }
      return result;
   }
}
0
 

Author Comment

by:Taurus
ID: 9891472
Objects,

Per wanting them removed from the hashtable, I want this because they are taking up a slot in the hashtable.  

I suppose I could use your wrapper class above in combination w/ jimmac's suggestion to "iterate through the Hashmap keys and when a value for a key is null, remove the key".  This might suffice but would it be as efficient???

So, why not just add a key member to the wrapper class, that in the example is extending WeakReference.  For example:

//inner weak ref class  see: http://builder.com.com/5100-6386-1049546.html
     public class wReference extends WeakReference {  
         Object Key; //adding a member for the Key
         public wReference( Object ref ){  
             super( ref );
         }  
         public wReference( Object id, Object ref, ReferenceQueue q ){    
             super( ref, q );
             Key = id;
         }
         public String toString() {    return String.valueOf(get());  }
    }

then per my beginning post, I add WeakReferenced objects to my hashtable with:

htobjects.put(id, new wReference(id, value,refQueue));

And the thread method that polls the refQueue becomes:

 public void run() {
         while ( true ) {        
             Reference ref = refQueue.poll();  
             if ( ref == null )          
                 break;      
             htobjects.remove( ((wReference)ref).Key );
             //insert delay
           }
     }

And what would be the thread sync issue(s)?  Aren't the Java Hashtable functions thread safe?




0
 
LVL 92

Expert Comment

by:objects
ID: 9891483
> I want this because they are taking up a slot in the hashtable.  

why exactly does that matter?
0
 

Author Comment

by:Taurus
ID: 9894693
I guess because I thought I might have to check the HT each time I do an insertion (assuming that the HT is going to be large and that collisions will occur not too infrequently with 32 bit keys).  Also, I might use other containers that aren't HTs, but that still take key/value pairs, and want to do similarly.  

Do you see a problem with what I offered above?  And what still about the thread sync issues?  I'm interested in what you think.
0
 
LVL 92

Expert Comment

by:objects
ID: 9894864
> I might have to check the HT each time I do an insertion

ht collisions are the responsibility of the implementation are shouldn't be your concern.

> I might use other containers that aren't HTs

The approach above would work with any Map.

> Do you see a problem with what I offered above?

You'd need to still wrap the map in your own class to handle attempts to access instances that have been cleared. So I don't see any real significant advantages to it, unless you start experiencing perormance problems due to collision clashes.
0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 

Author Comment

by:Taurus
ID: 9897378
>The approach above would work with any Map.

Do you mean your approach, or my approach, or both?

>You'd need to still wrap the map in your own class to handle attempts to access instances that have been cleared.

You mean like you did above, right?  
 
>So I don't see any real significant advantages to it, unless you start experiencing perormance problems due to collision clashes.

Any reason not to just combine your method and mine?  And don't we have to check also for weakref ref being assigned null:

public Object get(Object key)
   {
      WeakReference ref = () Refs.get(key);
      if(ref==null) return ref;
      Object result = ref.get();
      if (result==null)
      {
         Refs.remove(key);
      }
      return result;
   }

Combining both seems like it would be more generic and apply to other type situations where perhaps I was using another type of map and keys that weren't neccessarily related to a hashcode, say for example keys that get reused.

Finally, what did you mean by thread sync issues?



0
 

Author Comment

by:Taurus
ID: 9897882
On second thought per:
>>You'd need to still wrap the map in your own class to handle attempts to access instances that have been cleared.

Are you certain?  Since, "A reference object’s get method returns the object passed to the reference object’s constructor, or it returns null if the clear method has been called."

I see it being neccessary if the hashtable doesn't implicitely call the weakref's get().  Do you know if that is the case?
0
 

Author Comment

by:Taurus
ID: 9897914
In thinking about it, I assume it doesn't implicitely call weakref's get().
0
 

Author Comment

by:Taurus
ID: 9898224
How does this look?:

import java.util.Enumeration;
import java.util.Hashtable;

//needed for weak/soft references
import java.lang.ref.*;

public class simHT extends Thread
{
   
    ReferenceQueue refQueue = new ReferenceQueue();  
   
    protected Hashtable htobjects = new Hashtable();
   
    public void addObject(Object id, Object value)
      {
          htobjects.put(id, new wReference(id, value,refQueue));
      }
    public value getObject(Object id)
      {
                 wReference result;
                 //get weakreference from HT
                 result = (wReference)htobjects.get(id);
                 //check if weak reference has not already been removed
                 value Value = (value)result.get();
                 if (result==null)
                  {
                     htobjects.remove(id);
                  }
                 
                 return Value;
                 
      }
   

    public int getNumofValues()
      {
             Enumeration e = htobjects.elements();
            int numofvalues = 0;
                Object key;
                while(e.hasMoreElements())
            {
                  key = e.nextElement();
                        numofvalues++;
            }
                return numofvalues;
                 
      }
   
     public simHT(){

         //addObject(this.key1, this.value1);
     }
     
     public void run() {
         Reference ref;
         while ( true ) {        
             ref = refQueue.poll();  
             if ( ref != null )
             {
                htobjects.remove( ((wReference)ref).Key );
                ref.clear();
             }
             Thread.currentThread().sleep(100);
         }
        }
   
     
     //inner weak ref class  see: http://builder.com.com/5100-6386-1049546.html
     public class wReference extends WeakReference {  
         Object Key;
         public wReference( Object ref ){  
             super( ref );
         }  
         public wReference( Object id, Object ref, ReferenceQueue q ){    
             super( ref, q );
             Key = id;
         }
         public String toString() {    return String.valueOf(get());  }
    }

 
}
0
 
LVL 92

Expert Comment

by:objects
ID: 9899759
that should work, though I'm not convinced the thread is needed. If you do any benchmarking I'd be interested in the results.

A few minor points:
- the remove in getObject may attempt to remove an object that has already been removed (by polling thread) but this won't cause a problem.
- getNumofValues() method does not need to loop, it can use size() method. Though this # may include cleared values.
- do you need to clear() the object pulled off the queue, or has this already been done?
0
 

Author Comment

by:Taurus
ID: 9900407
> do you need to clear() the object pulled off the queue, or has this already been done?


The article says it is cleared when it is added to the reference queue.  I'll let you know when I do some benchmarking.  Thanks for your assistance on this.
0
 
LVL 92

Expert Comment

by:objects
ID: 9900444
0
 
LVL 15

Expert Comment

by:jimmack
ID: 9900459
;-)
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now