Object x = aChannel.take(); if (x instanceof EndOfStream) // special actions; perhaps terminate else // process normally
In time-out based methods (poll(msecs) and offer(x, msecs), time bounds are interpreted in a coarse-grained, best-effort fashion. Since there is no way in Java to escape out of a wait for a synchronized method/block, time bounds can sometimes be exceeded when there is a lot contention for the channel. Additionally, some Channel semantics entail a ``point of no return'' where, once some parts of the operation have completed, others must follow, regardless of time bound.
Interruptions are in general handled as early as possible in all methods. Normally, InterruptionExceptions are thrown in put/take and offer(msec)/poll(msec) if interruption is detected upon entry to the method, as well as in any later context surrounding waits.
If a put returns normally, an offer returns true, or a put or poll returns non-null, the operation completed successfully. In all other cases, the operation fails cleanly -- the element is not put or taken.
As with Sync classes, spinloops are not directly supported, are not particularly recommended for routine use, but are not hard to construct. For example, here is an exponential backoff version:
Object backOffTake(Channel q) throws InterruptedException { long waitTime = 0; for (;;) { Object x = q.poll(0); if (x != null) return x; else { Thread.sleep(waitTime); waitTime = 3 * waitTime / 2 + 1; } }
Sample Usage. Here is a producer/consumer design where the channel is used to hold Runnable commands representing background tasks.
class Service { private final Channel channel = ... some Channel implementation; private void backgroundTask(int taskParam) { ... } public void action(final int arg) { Runnable command = new Runnable() { public void run() { backgroundTask(arg); } }; try { channel.put(command) } catch (InterruptedException ex) { Thread.currentThread().interrupt(); // ignore but propagate } } public Service() { Runnable backgroundLoop = new Runnable() { public void run() { for (;;) { try { Runnable task = (Runnable)(channel.take()); task.run(); } catch (InterruptedException ex) { return; } } } }; new Thread(backgroundLoop).start(); } }
[ Introduction to this package. ] @author Doug Lea @author Last changed by: $Author: gommma $ @version $Revision: 766 $ $Date: 2008-08-01 13:05:20 +0200 (ven, 01 ago 2008) $ @since ? (pre 2.1) @see Sync @see BoundedChannel
|
|
|
|