Solved

How to use reference queue with Hashtable objects?

Posted on 2003-12-05
16
753 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
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 
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
 

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

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
eclipse formatting 6 87
Groovy problem when using SOAPUI : DispatchException occurred 7 43
web application structure 18 76
Java exception bubble up 2 17
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …

786 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