0

Synchronization question:

Set s = Collections.synchronizedSet(new HashSet());
private Object monitor_ = new Object();

//Set has element added in another routine...

//Called by some thread1, thread2, ...
TimerTask run(){ //method which executes every 1 min
  synchronized(monitor_) {
  s.isEmpty()
  // ...
  // waits for 30 seconds
  // JNI call
  // ...
 }
}

//Called by cleanup thread
removecall()
{
 synchronized( monitor_ ) {
   s.remove( something );
 }
}

Problem: While TimerTask run method is executing the cleanup thread has to wait. Any efficient way to handle this situation withut have to wait. e.g Re-entrant lock

Sandy
  • 112
  • 1
  • 8
  • can you give us the contents of `TimerTask.run()`? – Dan O Jun 22 '12 at 12:01
  • Your question is not very clear. Either you need the 2 operations in the timertask and in the cleanup thread to be synchronized or you don't. If your purpose is only to guarantee a thread safe access to your set, you don't need extra synchronization on top of using a synchronizedSet. – assylias Jun 22 '12 at 12:01
  • @assylias yes want safe acces of set, but as per java doc http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html#synchronizedSet(java.util.Set) It is imperative that the user manually synchronize on the returned set when iterating over it. – Sandy Jun 22 '12 at 13:02
  • @orzechowskid the run() calls a JNI method. – Sandy Jun 22 '12 at 13:04
  • A bit OT, but FYI Timer/TimerTask is semi-deprecated. Use Executors instead. See this thread for more info: http://stackoverflow.com/questions/409932/java-timer-vs-executorservice – ericsoco Aug 22 '12 at 18:53

4 Answers4

1

A concurrent Set might be the solution: CopyOnWriteArraySet or Collections.newSetFromMap(ConcurrentHashMap), but it's hard to say given what I know about your problem.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
0

You can communicate between threads easily if you use a ConcurrentLinkedQueue as the "messenger". Then you can simply put something inside that queue, for example a string that signalises if the thread is done working, e.g. public static String DONE = "DONE".

Now you only have to poll the queue every once in a while: if its not empty, you can perform any action. This makes your program flow really asynchronous and is very easy to extend.

devsnd
  • 7,382
  • 3
  • 42
  • 50
0

A couple of things come to mind:

  • When you call monitor_.wait(), the thread releases the lock on monitor_, so other threads synchornized on monitor_ can execute
  • The other option is that you just wait indefinetely, and override the methods that modify the hashset so that they call monitor_.notify(), which would get your run() method out of the wait(). This would be much cleaner than that periodic check, and would make the whole system react faster, since changes would be detected immediately instead of every (in average) 30seconds/2
Miquel
  • 15,405
  • 8
  • 54
  • 87
0

Try this, if you want both your work to be done concurrently, use 2 different objects in the synchronized block.

eg:

Set s = Collections.synchronizedSet(new HashSet());

private Object monitor_1 = new Object();
private Object monitor_2 = new Object();

TimerTask run(){ //method which executes every 1 min
  synchronized(monitor_1) {
  s.isEmpty()

 }
}


removecall()
{
 synchronized( monitor_2) {
   s.remove( pcg );
 }

}
Kumar Vivek Mitra
  • 33,294
  • 6
  • 48
  • 75