Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 760
  • Last Modified:

How to use reference queue with Hashtable objects?

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
Taurus
Asked:
Taurus
  • 8
  • 5
  • 3
2 Solutions
 
jimmackCommented:
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
 
TaurusAuthor Commented:
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
 
jimmackCommented:
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
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
objectsCommented:
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
 
TaurusAuthor Commented:
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
 
objectsCommented:
> I want this because they are taking up a slot in the hashtable.  

why exactly does that matter?
0
 
TaurusAuthor Commented:
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
 
objectsCommented:
> 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
 
TaurusAuthor Commented:
>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
 
TaurusAuthor Commented:
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
 
TaurusAuthor Commented:
In thinking about it, I assume it doesn't implicitely call weakref's get().
0
 
TaurusAuthor Commented:
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
 
objectsCommented:
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
 
TaurusAuthor Commented:
> 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
 
objectsCommented:
0
 
jimmackCommented:
;-)
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 8
  • 5
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now