• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Do I need wait() & notifyall()

 
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Forgive me for posting this here but that Threads and Synchronization forum just doesn't get as much traffic
This is in reference to this tutorial:Using the notifyAll and wait Methods
I have 3 synchronized functions that do the following (simplified for everyone's sake):
generateKey()- generates a Key object that stores 2 Date timestamps- the time of creation and expiration (ie. 10 mins. later) respectively- along with a String representing the key value. This object gets placed into a private member HashTable. I originally used HashMap but the synchronization issues led me to change to a HashTable

isValidKey(String checkMe)- obtains the Key object from the HashTable corresponding to the hashkey "checkMe" and checks if the expiration time has passed.

removeExpiredKeys()- Get's called by the run() function every 60 minutes and removes keys that are expired. This is pseudo-code to make it easier to read.

The run function looks like this:

From my main() I simply create one thread and let run() take care of everything. The functions generateKey and isValidKey are called from other classes at undetermined times. Worst case we've got thousands of calls to generateKey and isValidKey a minute.
After all of that, my question is Do I have to use wait() and notifyAll() like the tutorial states? Or because I'm using wait(long time) and not wait() I shouldn't be worried. The variable "hashTable" is the object that I want to ensure is synchronized between all those functions.
Thanks guys. I appreciate it.
 
Ranch Hand
Posts: 399
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'd be a bit concerned about whether the Hashtable.keys() Enumeration supports concurrent modification, and hence whether it might do the wrong thing if you remove a key from the map while you are walking through the Enumeration. Unless you can verify that the remove is OK, you may be better off using an Iterator, perhaps by replacing your HashTable with a HashMap wrapped using Collections.synchronizedMap(), as described in the JavaDoc for the class java.util.Collections.
Once you are working with a synchronized Map using synchonization during the iteration, as described in the documentation, and assuming you are not modifying the hashTable variable itself, just the synchronized Map to which would refer, you don't need to synchronize isValidKey() and generateKey(), unless something else in there requires synchronization, like Key().
It is not obvious why you are using wait(long) instead of Thread.sleep(long).
(I'm not a thread guru, but since you have not gotten a response, I'm trying to answer best I can with the understanding I have. Someone who uses threads and Hashtable more might be able to give you better news. It may be that for this purpose, Hashtable is equivalent to HashMap wrapped with Collections.synchronizedMap(); I just don't know.)
 
Ranch Hand
Posts: 1209
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
am not sure if am getting you right. Even i'm not able to appreciate the use of wait() in run(). It seems that Thread.sleep() s'd do the job.
I thought we use a wait() when we are actually waiting for something to happen.
I mean something like ,you are waiting for a flag to be set to true. But that action occurs in another syncronized method (say modify()).
So there is no point looping in an infinite while loop since that essentially blocks other threads from calling modify(). So we abandon the lock and allow someone else to acquire the lock and call modify().
That method must call notifyAll() or notify() once it is done since other threads might be waiting for that event to occur before proceeding.
In your case i don't see that happening OR am missing something :-(
In your case,
even the expiry time is predetermined i guess.
I mean there is no method which allows to force the key expiration.
As for synchronizing the access to the Hashtable, well, i guess as long as the methods that access them are syncronized, it s'd be fine.
 
David Duran
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hahaha, I appreciate the responses guys. A little feedback always helps.
John: I did a little reading on the Collections framework and have already switched over to a synchronized HashMap as well as replaced the Enumeration with an Iterator.

I'm confused, however, with your 2nd paragraph. If generateKey() and isValidKey() don't need to be synchronized I'd sure like to know!
As for using wait() instead of sleep(), I did it just for "safety" according to the tutorial:

Note: Besides using these timed wait methods to synchronize threads, you also can use them in place of sleep. Both wait and sleep delay for the requested amount of time, but you can easily wake up wait with a notify but a sleeping thread cannot be awakened prematurely. This doesn't matter too much for threads that don't sleep for long, but it could be important for threads that sleep for minutes at a time.


[ March 15, 2002: Message edited by: David Duran ]
 
John Dale
Ranch Hand
Posts: 399
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
According to the API documentation, you need to synchronize on the synchrononized Map object when using its Iterator. To quote the API documentation for Collections.synchronizedMap(Map):
"It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views". The API documentation gives an example.
I'm saying you probably don't need to synchronize the the two methods based on these assumptions: (1) you never modify the variable hashTable after the containing object is constructed, and (2) Key.isExpired() is thread-safe, and (3) you fix removeExpiredKeys() to synchronized on the synchronizedMap as specified in the documentation. If those assumptions are correct, I think you can get by without synchronization of the methods because generateKey() and isValidKey() refer to the synchronized Map only once, and through a thread-safe method. But unless the code called in Key refers back to the calling class, I don't see that synchronizing the methods can hurt much.
You might get a more conclusive response from someone expert in this in the threads forum. Even though more people read this forum, they may not be as good using or explaining thread issues.
Since you probably don't mind if removeExpiredKeys() runs more often than once per hour, I don't see that using wait instead of sleep hurts, unless something is doing very frequent notifies on the containing object.
 
David Duran
Ranch Hand
Posts: 122
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks John. I actually posted this over there and it sat there for 2 days so I tried my luck here.
I didn't even know about the additional documentation regarding Collections.synchronizedMap() in the javadoc until you mentioned "...during the iteration, as described in the documentation". I only knew of calling that function and not iterating over a synchronized block. #3 is taken care of. #2 is ok. #1 though, if I call remove() on an iteration, it does change the HashMap object after I created it so I don't believe condition 1 is true.

I think you can get by without synchronization of the methods because generateKey() and isValidKey() refer to the synchronized Map only once, and through a thread-safe method


What "thread-safe method" are you referring to? put() & get()?
[ March 15, 2002: Message edited by: David Duran ]
 
John Dale
Ranch Hand
Posts: 399
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
My point (1) is that you don't change the variable keyMap, the variable that REFERS to the object which is a synchronized Map. keyMap.remove() changes the object to which keyMap refers, not the reference variable keyMap itself. My guess is you declare and initalized keyMap something like
Map keyMap = new Collections.synchronizedMap(new HashMap());
and never change the variable keyMap itself, only the object to which it refers. You might even make keyMap final, so you be sure the reference never gets changed.
As for your final question, yes, I am referring to get and put of the Map returned by synchronizedMap.
[ March 15, 2002: Message edited by: John Dale ]
 
Don't get me started about those stupid light bulbs.
reply
    Bookmark Topic Watch Topic
  • New Topic