|
|
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 3 of 6
I've solved the problem of implementing a synchronous dispatcher with the Synchronous_dispatcher class in Listing 1. You can use the dispatcher in two ways. First of all, tasks can be added independently and then executed. The following
code prints the string "hello world" three times.
Synchronous_dispatcher dispatcher = new Synchronous_dispatcher();
dispatcher.add_handler( new Runnable()
{ public void run(){ System.out.print("hello "); }
}
);
dispatcher.add_handler( new Runnable()
{ public void run(){ System.out.print("world\n"); }
}
);
dispatcher.dispatch( 3 );
You can add a time delay between each chunk as follows:
dispatcher.metered_dispatch( 2, 1000 ); // one second delay between chunks
This call prints the following:
hello<pause>world<pause>hello<pause>world
A second version of add_handler() is provided to add an entire array of Runnable chunks to the dispatcher. The elements of the array are distributed as evenly as possible among the previously added chunks.
For example, the following code prints "Hello (Bonjour) world (monde)":
Runnable[] first_task =
{ new Runnable(){ public void run(){ System.out.print("Hello"); }},
new Runnable(){ public void run(){ System.out.print(" world");}}
};
Runnable[] second_task =
{ new Runnable(){ public void run(){ System.out.print(" (Bonjour)");}},
new Runnable(){ public void run(){ System.out.print(" (monde)" );}}
};
dispatcher = new Synchronous_dispatcher();
dispatcher.add_handler( first_task );
dispatcher.add_handler( second_task );
dispatcher.dispatch( 1 );
The chunks of a task can share data, if necessary, through the instance variables of the class that contains the array definitions.
Of course, several dispatchers can each run on their own threads, in which case you have a situation much like Sun's "green thread" model, where cooperative and preemptive threads both share the same process.
Looking at the implementation, the individual Runnable chunks are kept in the events LinkedList (Listing 1, line 9). The one-element version of add_handler(Runnable) (Listing 1, line 12) just tacks the new element onto the end of the list. The array version add_handler(Runnable[]) (Listing 1, line 17) is trickier to implement than you might expect. This is because the incoming array could be larger than the existing list
(in which case you want the existing list elements dispersed evenly between array elements), or smaller than the existing
list (in which case you want the incoming array elements to be dispersed evenly throughout the existing list). I've chosen
to make matters easier by first converting the list to an array so that I can work with two similar data structures. I then
rebuild the linked list, first copying one or more elements from the larger array into the list, then copying one element
from the smaller array, then one or more elements from the larger array, and so forth. An earlier version of this method did
the same thing without first doing the list-to-array conversion, but it was both considerably more complex and slower then
the current version.