|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 4 of 5
An alternative to the solution in Listing 1 would be to encapsulate the code from the instance initializer in a nonstatic method, and then call it when initializing the field:
new Thread()
{ int length;
byte[] copy = init();
private void init()
{ length = Flush_example.this.length;
byte[] copy = new byte[length];
System.arraycopy(Flush_example.this.buffer, 0, copy, 0, length);
Flush_example.this.length = 0;
return copy;
}
//...
}
This isn't much of an improvement over the instance initializer in clarity, and initializing length as a side effect of the init() call is particularly hideous. I've used arraycopy() rather than clone because I didn't want to mess with the CloneNotSupportedException. Exceptions are not allowed to propagate out of instance initializers.
Whatever method we use for initialization, the inner-class's construction happens in the new() on line 20 of Listing 1, while the outer-class object is locked, so the copy operation is thread-safe. The newly-created thread then
acquires the writer lock and writes to the file in its own good time, using the copy for this purpose.
|
An exceptional problem
The next perplexing issue is what to do with the IOException. Back in the original version of the code, the exception propagated out of the flush() method to whomever called flush(). We can't do that here, because there's nobody to propagate it to -- if you start backtracking down the call stack, you'll end up back in run(), but you didn't call run(); the system did when it fired up the thread. Simply ignoring the write error, as I've been doing, isn't a good strategy for
obvious reasons.
One solution to this problem is the Observer pattern discussed in March. (AWT's listeners, for example, are observers.) The method that finally catches the IOException must be a method that calls flush(), either directly or indirectly, so this method could simply register a listener and be notified when something goes wrong.
In the current situation, a full-blown observer is something of an overkill, however. After all, there will only be one observer
for a given I/O operation.