// File: Amplifier.java
// Provides a method for searching an array of double numbers for a target.
// It's primary purpose is to introduce concurrent processing in Java.
// Additional javadoc documentation is available from the Amplifier link at:
// http://www.cs.colorado.edu/~main/docs
package edu.colorado.concurrent;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.Vector;
/******************************************************************************
* The Amplifier
class implements a method that can search an array
* of double numbers for a specified target. It's primary purpose is to
* introduce concurrent processing in Java.
*
*
firstIndex
<= hiIndex
<= data.length
* @param data
* the array to be searched
* @param loIndex
* the start index for the portion of the array that will be searched
* @param hiIndex
* the index just beyond the end of the portion of the array to be searched
* @param target
* the number to be searched for within part of the array
* @exception NullPointerException
* Indicates illegal values of loIndex
or hiIndex
.
* @exception ArrayIndexOutOfBoundsException
* Indicates illegal values of loIndex
or hiIndex
.
**/
public Amplifier(double[] data, int loIndex, int hiIndex, double factor)
{
// Check that the indices are valid:
if (0 > loIndex || loIndex > hiIndex || hiIndex > data.length)
throw new ArrayIndexOutOfBoundsException("Illegal indices");
// Copy the parameters to the instance variables:
this.data = data;
this.loIndex = loIndex;
this.hiIndex = hiIndex;
this.factor = factor;
}
/**
* Do the work to increase the elements of the array by the factor.
* factor
is within the part of the array from
* data[loIndex]
up to but not including
* data[hiIndex]
, then the return value is some index i
* with data[i] == factor
. Otherwise, this method
* throws an exception as described below.
* @exception Exception
* Indicates that the factor
is not present in the specified
* portion of the array.
* concurrentSearch
* method.
**/
public void run( )
{
int i;
for (i = loIndex; i < hiIndex; i++)
{
data[i] *= factor;
}
}
/**
* Use Amplifier objects to concurrently search of part of an array for a factor.
* firstIndex
<= hiIndex
<= data.length
* and manyThreads > 0.
* @param data
* the array to be searched
* @param loIndex
* the start index for the portion of the array that will be searched
* @param hiIndex
* the index just beyond the end of the portion of the array to be searched
* @param factor
* the number to be searched for within part of the array
* @param manyThreads
* how many different Amplifier objects to use, each in a different thread
* factor
is within the part of the array from
* data[loIndex]
up to but not including
* data[hiIndex]
, then the return value is some index i
* with data[i] == factor
. Otherwise, the return value is -1.
* @exception IllegalArgumentException
* Indicates that manyThreads <= 0.
* @exception ArrayIndexOutOfBoundsException
* Indicates illegal values of loIndex
or hiIndex
.
**/
public static boolean concurrentRun
(double[] data, int loIndex, int hiIndex, double factor, int manyThreads)
{
// The executor runs the pieces concurrently:
ExecutorService executor = Executors.newFixedThreadPool(manyThreads);
int pieceSize = (hiIndex - loIndex)/manyThreads; // Size of most pieces
int finalStart = loIndex + pieceSize*(manyThreads-1); // Start of last piece
int start, end; // Indices for the start and end of one piece
int i; // Loop control variable
final long LIMIT = 86400; // Limit on runtime of 86400 seconds
// Validate the preconditions:
if (manyThreads <= 0)
throw new IllegalArgumentException("manyThreads must be positive");
if (0 > loIndex || loIndex > hiIndex || hiIndex > data.length)
throw new ArrayIndexOutOfBoundsException("Illegal indices");
// Submit all the threads except the final one (since it may be bigger):
for (i = 0; i < manyThreads-1; i++)
{
start = loIndex + pieceSize*i;
end = start + pieceSize;
executor.submit(new Amplifier(data, start, end, factor));
}
// Add final thread, and let executor know there will be no more threads:
executor.submit(new Amplifier(data, finalStart, hiIndex, factor));
executor.shutdown( );
try
{ // Wait for the submitted threads to complete their work.
return executor.awaitTermination(LIMIT, TimeUnit.SECONDS);
}
catch (InterruptedException e)
{ // Someone requested an early shutdown (see text for how we handle this):
Thread.currentThread( ).interrupt( );
return false;
}
}
}