I've been reading up on the new concurrency utilities in java.util.concurrent. Overall, I'm very impressed. But what I think is particularly interesting is how well generic types fit with the "Executors" framework of these utilities. Here's a brief rundown:
An ExecutorService executes things, like Runnable objects. Different implementations of ExecutorService can use different threading strategies. One might queue things up for execution on a single shared thread. Another might create a new thread for every Runnable. And another might implement a thread pool.
The concurrency utilities also generalize the notion of a Runnable. A Callable is a chunk of code that can return a result or throw an exception (a Runnable can do neither). Callable is parameterized with the type of its return value. So a Callable that does a floating-point computation might be a Callable<Double>.
ExecutorService can asynchronously execute Callable objects as well as Runnable objects. Since a Callable returns a result, however, the ExecutorService returns a Future object as a placeholder for the future result of the executing Callable. Like Callable, Future is parameterized with the result type. So, if you call the submit() method of an ExecutorService and pass it a Callable<Double>, the return value of submit() is a Future<Double>. When you're ready to retrieve the result of the computation, you just call the get() method of the Future<Double> object. It blocks, if necessary, until the computation is done, and returns the result. Thanks to auto-unboxing, you don't have to mess with a Double object and can just store this result into a primitive double variable.
Future<Double>.... How lovely! An elegant name that captures the meaning of the type. My point, I guess, is that a well-crafted API like this demonstrates that generics are indeed useful beyond their canonical use-case of collections.
A related question is how hard is it to create a well-crafted generic API? That is, can ordinary Java programmers (who are not primarily API designers) create APIs that use generics elegantly and effectively? Or will we end up with poorly-designed, hard-to-understand APIs created using generics simply because they were there? Time will tell, I suppose. Bill Dudney wonders about this in his blog. (Ignore his remarks about e-mailing the generics expert group, though. The public-review period has long since ended, and the Tiger release schedule is hard upon the implementors: there is no time for further changes.)
And don't forget to read up on concurrency. Its a really sweet package .



