Thursday, November 20, 2008

Time's Up

I'm certainly not the first person to say this, but it bears repeating, using Timer in the post Java 5 world is not a good idea. I got bitten by Timer's lack of exception handling again recently. If you must use a Timer and are relying on it to be long-lived, make sure the run() methods on your tasks can't throw any unchecked exceptions, because if any exceptions manage to leak out of the run() method, the timer thread will terminate and no more tasks will run. I used to use Timer in situations where I wanted to be able to cancel tasks, since TimerTask exposes a cancel() method. What I failed to realize was that you can do the exact same thing using ScheduledExecutorService using the ScheduledFuture object that is returned when one of the schedule methods is invoked. It's a bit more cumbersome to cancel tasks this way since you may have to keep references to both the task object and the future object, but it wouldn't be too difficult to create a custom class to manage this.

Monday, November 10, 2008

Who's the Boss?

JBoss Cache 3.0.0 is almost ready, and its big feature, multi-version concurrency control (MVCC), is a big improvement. I assume that anyone who has tried to do anything interesting with JBoss Cache has run into this limitation: any time you try and upgrade a read lock to a write lock while another thread is holding a read lock on the same node, you get an UpgradeException. Preventing this situation from arising in an application is very complicated. You can use Java synchronization to prevent concurrent access to the same data, but then you're throwing away JBoss Cache's fine-grained locking system. The solution that I settled on was a fine-grained (but not hierarchical) java.util.concurrent.locks.Lock-based layer that prevented concurrent access to the same cache nodes. JBoss Cache 3.0.0 makes all of this code unnecessary. In a pinch me, I'm dreaming moment, I wrote this test (adapted from the TxDeadlockUnitTestCase) that causes the JBCACHE-97 bug and ran it against a 3.0.0 CR3 and 2.1.1 GA just to make sure the problem is really gone.