|
Apache Jakarta Commons(c) Reusable Java Components Authors: Iverson W. Published year: 2006 Pages: 38-39/137 |
|
|
|
Object Factory ExampleThe object factory, shown in Listing 5-2, implements the PoolableObjectFactory interface. The two key methods implemented are makeObject() and validateObject() . The factory always returns false for an invalid object because when a thread enters a finished state, it cannot be reused. Because the pool is configured to always test on return (as shown in Listing 5-1), this means that the WorkerThread will be removed when completed. Listing 5-2. Thread Factory
package com.cascadetg.ch05;
import org.apache.commons.pool.PoolableObjectFactory;
public class WorkerThreadFactory implements PoolableObjectFactory
{
/** Keeps track of the currently created thread. */
public int currentThread = 0;
/** Create and name the thread. Naming the thread is very
* helpful when trying to debug multi-threaded applications.
*/
public Object makeObject() throws Exception
{
WorkerThread temp = new WorkerThread();
temp.setName("Worker Thread #" + currentThread++);
return temp;
}
/** We aren't reusing threads, so we always return false here,
* causing the pool to remove this thread from the pool and
* create a new object using the makeObject() method.
*/
public boolean validateObject(Object arg0) { return false; }
public void destroyObject(Object arg0) throws Exception { }
public void activateObject(Object arg0) throws Exception { }
public void passivateObject(Object arg0) throws Exception { }
}
|
|
|
|
|
|
|
Worker ThreadListing 5-3 shows our worker thread. The default implementation merely counts to 1,000, yielding every count. This is overly aggressive , but it does allow the system to remain highly responsive to other threads during execution. It's easy to imagine changing the behavior of this worker thread to do something more computationally complexfor example, when used in conjunction with the networking capabilities shown in Chapter 4, "Net" and this chapter, parallel execution could well be much faster and easier. The implementation shown in Listing 5-3 drops out of the run() method when complete, rendering the thread no longer reusable. It would be possible to create a reusable WorkerThread instead of completing and dropping out of the run() method, the thread could instead have two statesa busy state and an idle state, with the thread returning itself to the pool when switching from the busy state to idle. Listing 5-3. Worker Thread
package com.cascadetg.ch05;
import org.apache.commons.pool.ObjectPool;
public class WorkerThread extends Thread
{
// The total amount of work done by the threads.
static public long totalUnits = 0;
// The number of times the thread should look over a counter
// (this is our definition of work)
private int counter = 1000;
// When the thread is done, it returns itself to the pool.
private ObjectPool hostPool = null;
// Used to indicate that a thread, when completed, is no longer
// useful.
public boolean valid = true;
public void setPool(ObjectPool myPool)
{
hostPool = myPool;
}
public void run()
{
// Loop over a counter, and yield each time to allow other
// threads to execute. In a "real" app, you wouldn't need
// to yield anywhere near this often.
for (int i = 0; i < counter; i++)
{
totalUnits++;
yield();
}
try
{
// We synchronize on the pool to avoid possible
// threading problems, and return our object.
synchronized (hostPool)
{
this.valid = false;
hostPool.returnObject(this);
}
} catch (Exception e)
{ e.printStackTrace(); }
}
}
Finally, Listing 5-4 shows an example of the output of this application. Paying close attention to the output, we can see that in this particular case, a non-parallel approach has the best timing. This is to be expected in a CPU- dependent, single system environment, but in environments involving potentially slow resources (such as network access), the results may be quite different. Listing 5-4. Sample OutputStarting 30/30 Total created threads:30 Seconds Elapsed: 0.191 Completed: 30000 units/second: 157068.06 Starting 100/100 Total created threads:100 Seconds Elapsed: 0.801 Completed: 100000 units/second: 124843.945 Starting 1000/1000 Total created threads:1000 Seconds Elapsed: 9.794 Completed: 1000000 units/second: 102103.33 Starting 1000/2000 Total created threads:2000 Seconds Elapsed: 19.127 Completed: 2000000 units/second: 104564.23 Starting 1/3000 Total created threads:3000 Seconds Elapsed: 5.398 Completed: 3000000 units/second: 555761.44 Starting 10/3000 Total created threads:3000 Seconds Elapsed: 6.85 Completed: 3000000 units/second: 437956.22 Starting 30/3000 Total created threads:3000 Seconds Elapsed: 7.641 Completed: 3000000 units/second: 392618.78 Starting 1000/3000 Total created threads:3000 Seconds Elapsed: 28.471 Completed: 3000000 units/second: 105370.375 Most efficient @ 555761.44 (1/3000) Done. |
|
|
|
|
Apache Jakarta Commons(c) Reusable Java Components Authors: Iverson W. Published year: 2006 Pages: 38-39/137 |