I have a singleton logger that contains a vector. Objects from outside can append information to this vector by calling singletonLogger.append(String data) and read the whole vector by calling singletonLogger.getLogEntries() which returns a string.
It would be nice to overload the getLogEntries-method with an int-parameter, e.g. getLogEntries(int x), to be able to get only the last x entries instead of the whole log.
Without regarding mutliple threads, this would be easy, something like:
String getLogEntries(int x) {
int size = vector.size();
for(int i = size; i > (size - x); i--) {
// StringBuilder.append(vector.elementAt....
}
}
But of course, this is not really safe when taking multiple threads into account. Imagine the vector gets cleared by another method shortly after its size was determined by the method above, the loop will crash.
On the other hand, I do not want to mark the whole method as synchronized, because the loop processing could last 5 – 10 seconds. This would block all the code that is trying to call the logger’s methods, right?
Is there another way to reliably get the last x elements of a vector?
Thanks
Edit
Vector has a
sublistmethod that should work and be synchronized but that doesn’t solve someone clearing theVectorin another thread. You could useReadWriteLockand get areadLock()when reading from the end of theVectorusingsublist()and awriteLock()(which guarantees exclusive access) whenclear()needs to be called. If your background thread is writing the log entries to disk or something, it should count the number of line written, and then get awriteLock()and remove those from the front of the list instead of callingclear(). That would limit the time under the lock to be more efficient.You might also consider maintaining your own internal queue so you can control the synchronization specifically. This may make it easier to clear the earlier entries from the queue. Then again you may need a
ReadWriteLockfor that as well.