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?
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?
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.
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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?
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?
why exactly does that matter?
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.
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.
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.
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?
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?
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?
>>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?
ASKER
In thinking about it, I assume it doesn't implicitely call weakref's get().
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().sle ep(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()); }
}
}
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(
//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().sle
}
}
//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?
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?
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.
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.
;-)
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.