Link to home
Start Free TrialLog in
Avatar of Taurus
Taurus

asked on

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?

Avatar of jimmack
jimmack

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.
Avatar of Taurus

ASKER

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:

https://www.experts-exchange.com/questions/20783541/Does-Java-have-anything-akin-to-a-smart-pointer-for-referenced-objects.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.  
SOLUTION
Avatar of jimmack
jimmack

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Taurus

ASKER

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?




> I want this because they are taking up a slot in the hashtable.  

why exactly does that matter?
Avatar of Taurus

ASKER

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.
> 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.
Avatar of Taurus

ASKER

>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?



Avatar of Taurus

ASKER

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?
Avatar of Taurus

ASKER

In thinking about it, I assume it doesn't implicitely call weakref's get().
Avatar of Taurus

ASKER

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());  }
    }

 
}
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?
Avatar of Taurus

ASKER

> 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.
;-)