User: jung
Date: 00/12/22 07:43:25
Added: src/de/infor/ce/thread Environment.java How Pooling Should
Work .dfSequence PooledThread.java
PooledThreadLocal.java ThreadPool.java
thread.dfPackage
Log:
repackaged thread pooling. Coherent environment. Exception extensions.
Revision Changes Path
1.1 zoap/src/de/infor/ce/thread/Environment.java
Index: Environment.java
===================================================================
/*
* $Source: /products/cvs/ejboss/zoap/src/de/infor/ce/thread/Environment.java,v $
* The Zero-effort Object Access Package is a library to support XML/SOAP
serialisation and invocation.
* Copyright (c) 2000 infor business solutions AG, Hauerstrasse 12,
* D-66299 Friedrichsthal, Germany. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package de.infor.ce.thread;
import java.util.Properties;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import de.infor.ce.console.Console;
/**
* Environment contains static variables and other helping stuff that either
influence
* the compilation of the package or initialise its runtime environment from config
files.
* @author jung
* @version $Revision: 1.1 $
*/
public abstract class Environment {
//
// Place your non-final public statics here
//
//
// non-final public system statics
//
/** runtime logging settings */
public static int LOG_LEVEL = 1;
/** the properties belonging to this module */
public static Properties PROPERTIES = System.getProperties();
/** the logger for this module */
public static Console CONSOLE = null;
//
// final public system static
//
/** whether debug messages are produced, compile-time switch */
public static final int DEBUG_LEVEL = 0;
/** how this module is called */
public static final String MODULE_NAME =
Environment.class.getName().substring(0,
Environment.class.getName().length() - 12);
/** where the resources needed to configure this module are found */
public static final String RESOURCE_PATH = "";
/** whether a config file is loaded */
public static final boolean READ_CONFIG_FILE = false;
/** where the resources needed to configure this module are found */
public static final String CONFIG_FILE_SUFFIX = ".conf";
//
// static initialisation part, DO NOT MODIFY
//
/** initialisation is done at class loading time */
static {
try {
CONSOLE =
de.infor.ce.console.Environment.CONSOLE_FACTORY.createConsole(MODULE_NAME);
} catch (Exception e) { }
if (READ_CONFIG_FILE) {
try {
if (DEBUG_LEVEL > 0)
CONSOLE.log(Environment.class.toString() +
"_static initializer: trying to load
configuration resource file " +
RESOURCE_PATH + MODULE_NAME +
CONFIG_FILE_SUFFIX);
// and add your personal configuration file
PROPERTIES.load(Environment.class.getClassLoader().
getResourceAsStream(RESOURCE_PATH + MODULE_NAME +
CONFIG_FILE_SUFFIX));
} catch (Exception e) {
if (DEBUG_LEVEL > 0) {
CONSOLE.error(Environment.class.toString() +
"_static initializer: encountered " + e + "
while trying to load configuration resource file " +
RESOURCE_PATH + MODULE_NAME +
CONFIG_FILE_SUFFIX);
CONSOLE.exception(e);
}
}
}
try {
Field[] fields = Environment.class.getFields();
for (int count = 0; count < fields.length; count++) {
try {
if
(PROPERTIES.containsKey(fields[count].getName()) &&
Modifier.isStatic(fields[count].getModifiers()) &&
!Modifier.isFinal(fields[count].getModifiers())) {
if (DEBUG_LEVEL > 0)
CONSOLE.log(Environment.class.toString() +
"_static initializer: trying
to initialize field " + fields[count].getName()
+ " with configuration
property " +
PROPERTIES.getProperty(fields[count].getName()));
fields[count].setAccessible(true);
if
(fields[count].getType().equals(boolean.class) ||
fields[count].getType().equals(Boolean.class)) {
fields[count].set(Environment.class,
new
Boolean(PROPERTIES.getProperty(fields[count].getName())));
} else if
(fields[count].getType().equals(int.class) ||
fields[count].getType().equals(Integer.class)) {
fields[count].set(Environment.class,
new
Integer(PROPERTIES.getProperty(fields[count].getName())));
} else if
(fields[count].getType().equals(double.class) ||
fields[count].getType().equals(Double.class)) {
fields[count].set(Environment.class,
new
Double(PROPERTIES.getProperty(fields[count].getName())));
} else if
(fields[count].getType().equals(float.class) ||
fields[count].getType().equals(Float.class)) {
fields[count].set(Environment.class,
new
Float(PROPERTIES.getProperty(fields[count].getName())));
} else if
(fields[count].getType().equals(String.class)) {
fields[count].set(Environment.class, PROPERTIES.
getProperty(fields[count].getName()));
} else {
if (DEBUG_LEVEL > 0)
CONSOLE.warning(Environment.class.toString() +
"_static initializer:
type " + fields[count].getType().getName() + " of field " +
fields[count].getName() + " is not supported by the reflection configurator.");
}
}
} catch (Exception e) {
if (DEBUG_LEVEL > 0) {
CONSOLE.error(Environment.class.toString() +
"_static initializer: encountered " +
e + " while trying to initialise field " + fields[count].getName());
CONSOLE.exception(e);
}
}
}
} catch (Exception e) {
if (DEBUG_LEVEL > 0) {
CONSOLE.error(Environment.class.toString() +
"_static initializer: encountered " + e + " while
trying to get class fields");
CONSOLE.exception(e);
}
}
} // static
} // Environment
No revision
No revision
No revision
No revision
No revision
1.1 zoap/src/de/infor/ce/thread/PooledThread.java
Index: PooledThread.java
===================================================================
/*
* $Source: /products/cvs/ejboss/zoap/src/de/infor/ce/thread/PooledThread.java,v $
* The Zero-effort Object Access Package is a library to support XML/SOAP
serialisation and invocation.
* Copyright (c) 2000 infor business solutions AG, Hauerstrasse 12,
* D-66299 Friedrichsthal, Germany. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package de.infor.ce.thread;
import java.util.Map;
import java.util.Collections;
/**
* a thread that is part of a pool, maybe subclassed (I hope you know what you are
doing!) but has quite protected access
* @author jung
* @version $Revision: 1.1 $
*/
public class PooledThread extends Thread {
/** the pool to which this thread belongs */
final protected ThreadPool threadPool;
/** should this thread keep on running? should be only settable to false */
protected boolean running = true;
/** what would be the next task to perform? */
protected Runnable runnable;
/** list of pooled locals, protected access (@see PooledThreadLocal) */
protected Map pooledThreadLocals;
/** construct new pooled thread for a particular pool, protected constructor
*/
protected PooledThread(ThreadPool pool) {
super();
threadPool = pool;
init(null);
}
/** construct new thread with a given runnable */
protected PooledThread(ThreadPool pool, Runnable target) {
super();
threadPool = pool;
init(target);
}
/** new pooled thread assigned to a particular group */
protected PooledThread(ThreadPool pool, ThreadGroup group, Runnable target) {
super(group, (Runnable)null);
threadPool = pool;
init(target);
}
/** new thread with a given name */
protected PooledThread(ThreadPool pool, String name) {
super(name);
threadPool = pool;
init(null);
}
/** new thread with given group and name */
protected PooledThread(ThreadPool pool, ThreadGroup group, String name) {
super(group, name);
threadPool = pool;
init(null);
}
/** new thread with target and name */
protected PooledThread(ThreadPool pool, Runnable target, String name) {
super(name);
threadPool = pool;
init(target);
}
/** new thread with given group, runnable and name */
protected PooledThread(ThreadPool pool, ThreadGroup group, Runnable target,
String name) {
super(group, name);
threadPool = pool;
init(target);
}
/** initialise locals and such */
protected void init(Runnable initialRunnable) {
pooledThreadLocals = Collections.EMPTY_MAP;
running = true;
this.runnable = initialRunnable;
}
/** do something meaningful over a longer period of time */
public void run() {
if (Environment.DEBUG_LEVEL > 0)
Environment.CONSOLE.debug(toString() + ".run()");
while (running) {
if (runnable != null) {
try {
runnable.run();
} catch (Throwable t) {
// catch any throwable to continue working
if (Environment.DEBUG_LEVEL > 0 ||
Environment.LOG_LEVEL > 0) {
Environment.CONSOLE.error(toString() +
".run(): uncaught throwable " + t + " on pooled thread-level.");
Environment.CONSOLE.exception(t);
}
}
// Clear work, this is safe as the thread should be
non-pooled in this state
runnable = null;
}
// clean up the threads local values
clean();
// Return to pool
threadPool.returnThread(this);
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() + ".run(): going
to sleep.");
// Wait for work to become available
synchronized(this) {
if (running && runnable == null) {
try {
this.wait();
} catch (InterruptedException e) {
}
}
}
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() + ".run(): awake
from sleep.");
} // while
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() + ".run(): Left task
loop. I�m dead.");
} // run
/** this method allows to start an arbitrary runnable in this thread, is
guarantueed to run only once */
protected void run(Runnable runnable) {
if (Environment.DEBUG_LEVEL > 0)
Environment.CONSOLE.debug(toString() + ".run(" + runnable +
")");
synchronized(this) {
if (running && this.runnable == null) {
this.runnable = runnable;
this.notify();
} else {
if (Environment.DEBUG_LEVEL > 0 ||
Environment.LOG_LEVEL > 0) {
Environment.CONSOLE.error(toString() + ".run("
+ runnable +
"): could not run runnable because pooled
thread is dead or occupied. This hints to a major bug!");
}
// this should never, never happen
throw new RuntimeException(toString() + ".run(" +
runnable +
"): could not run runnable because pooled thread is
dead or occupied. This hints to a major bug!");
}
}
}
/** and finally, the signal to die ASAP */
protected void finalize() {
if (Environment.DEBUG_LEVEL > 0)
Environment.CONSOLE.debug(toString() + ".finalize()");
synchronized(this) {
if (running && runnable == null) {
running = false;
this.notify();
} else {
if (Environment.DEBUG_LEVEL > 0 ||
Environment.LOG_LEVEL > 0) {
Environment.CONSOLE.error(toString() +
".finalize(): could not terminate thread because its still loaded with
"+runnable.toString()+". This hints to a major bug!");
}
// this should never, never happen
throw new RuntimeException(toString() + ".finalize():
could not terminate thread because its still loaded. This hints to a major bug!");
} // if
} // sync
} // die
/** cleanup the locals */
protected void clean() {
if (Environment.DEBUG_LEVEL > 0)
Environment.CONSOLE.debug(toString() + ".clean()");
pooledThreadLocals = Collections.EMPTY_MAP;
}
} // PooledThread
1.1 zoap/src/de/infor/ce/thread/PooledThreadLocal.java
Index: PooledThreadLocal.java
===================================================================
/*
* $Source:
/products/cvs/ejboss/zoap/src/de/infor/ce/thread/PooledThreadLocal.java,v $
* The Zero-effort Object Access Package is a library to support XML/SOAP
serialisation and invocation.
* Copyright (c) 2000 infor business solutions AG, Hauerstrasse 12,
* D-66299 Friedrichsthal, Germany. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package de.infor.ce.thread;
import java.util.Map;
import java.util.Collections;
import java.util.HashMap;
/**
* a thread local that will be dumped if the corresponding thread will be
pooled.
* @see PooledThread, ThreadPool
* @author jung
* @version $Revision: 1.1 $
*/
public class PooledThreadLocal extends ThreadLocal {
/** this is to determine the initial size of the ThreadLocal-To-Value mappings
that are kept inside @see PooledThread */
public static final int INITIAL_SIZE = 11;
/** Creates a PooledThreadLocal */
public PooledThreadLocal() {
super();
noSpoofKey = new NoSpoof();
}
/** A trick known from JDK1.3 to prevent spoofing. */
protected Object noSpoofKey;
/** return the threadlocal value */
public Object get() {
if (Environment.DEBUG_LEVEL > 0)
Environment.CONSOLE.debug(toString() + ".get()");
// lookup current thread
Thread ourThread = Thread.currentThread();
// case-analysis
if (ourThread instanceof PooledThread) {
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() + ".get():
current thread " + ourThread + " is pool-enabled.");
// a pooled thread uses the extended feature
Map map = ((PooledThread)ourThread).pooledThreadLocals;
Object value = map.get(noSpoofKey);
if (value == null && !map.containsKey(noSpoofKey)) {
if (map == Collections.EMPTY_MAP)
map =
((PooledThread)ourThread).pooledThreadLocals =
new HashMap(INITIAL_SIZE);
value = initialValue();
map.put(noSpoofKey, value);
}
return value;
} else {
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() + ".get():
current thread " + ourThread + " is not pool-enabled.");
// a normal thread behaves as usual
return super.get();
}
}
/** set the threadlocal value */
public void set(Object value) {
if (Environment.DEBUG_LEVEL > 0)
Environment.CONSOLE.debug(toString() + ".set(" + value + ")");
// lookup current thread
Thread ourThread = Thread.currentThread();
// case analysis
if (ourThread instanceof PooledThread) {
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() + ".set(" + value
+ "): current thread " + ourThread + " is pool-enabled.");
// pooled threads have that special feature
Map map = ((PooledThread)ourThread).pooledThreadLocals;
if (map == Collections.EMPTY_MAP)
map = ((PooledThread)ourThread).pooledThreadLocals =
new HashMap(INITIAL_SIZE);
map.put(noSpoofKey, value);
} else {
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() + ".set(" + value
+ "): current thread " + ourThread + " is not pool-enabled.");
// normal threads don�t
super.set(value);
}
}
/** Prevent spoofing by this hidden class */
private class NoSpoof {
}
} // PooledThreadLocal
1.1 zoap/src/de/infor/ce/thread/ThreadPool.java
Index: ThreadPool.java
===================================================================
/*
* $Source: /products/cvs/ejboss/zoap/src/de/infor/ce/thread/ThreadPool.java,v $
* The Zero-effort Object Access Package is a library to support XML/SOAP
serialisation and invocation.
* Copyright (c) 2000 infor business solutions AG, Hauerstrasse 12,
* D-66299 Friedrichsthal, Germany. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package de.infor.ce.thread;
import java.util.Stack;
import java.util.Iterator;
/**
* Implementation of a threadpool
* @author jung
* @version $Revision: 1.1 $
*/
public class ThreadPool {
/** we pool the threads in a stack */
protected final Stack pool = new Stack();
/** we log the number of yet created threads */
protected int active;
/** the maximum size of that pool */
protected int maxSize;
/** whether the pool blocks on non-availability */
protected boolean blocks;
/** the name associated to the threads */
protected String threadName;
/** whether threads are started in demon mode */
protected boolean daemon;
/** constructor takes the @arg maxSize of that pool and the @arg blocks flag
as its arguments. */
public ThreadPool(int maxSize, boolean blocks, String threadName, boolean
whetherDaemon) {
if (Environment.DEBUG_LEVEL > 0)
Environment.CONSOLE.debug(toString() + "(" + maxSize + "," +
blocks + "," +
threadName + "," + whetherDaemon + ")");
this.maxSize = maxSize;
this.blocks = blocks;
this.threadName = threadName;
this.daemon = whetherDaemon;
}
/** sets the maximum size */
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
/** gets the maximum size */
public int getMaxSize() {
return maxSize;
}
/** asks whether this pool is in blocking mode */
public boolean doesBlock() {
return blocks;
}
/**
* sets the blocking mode and awakes all the waiting "external" threads that
* aim to upload some runnables but have been suspended because of former
blocking
*/
public void setBlocks(boolean blocks) {
this.blocks = blocks;
pool.notifyAll();
}
/**
* use an available thread from your pool to run the given runnable @arg work
* if the pool is empty and we are in blocking mode this method will block
until a thread is returned to the pool
* otherwise a new thread is returned in each case
*/
public void run(Runnable runnable) {
if (Environment.DEBUG_LEVEL > 0)
Environment.CONSOLE.debug(toString() + ".run(" + runnable +
")");
// first synchronized on the stack
synchronized(pool) {
// the pool is empty
if (pool.isEmpty()) {
// and we have been given out all the threads that we
can afford in blocking mode
if (doesBlock() && active >= maxSize) {
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() +
".run(" + runnable + "): pool is empty and blocking mode on. Suspending.");
// then wait until something is returned into
the pool
// or the blocking mode has been changed
try {
pool.wait();
} catch (InterruptedException e) { }
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() +
".run(" + runnable + "): pool reconfigured. Trying again.");
// and try again, hope that the stack will not
become
// too deep by that call!
run(runnable);
} else {
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() +
".run(" + runnable + "): pool empty, but non-blocking. Creating new PooledThread.");
// in non-blocking mode or in the case of an
undersatisfied pool,
// we can create as many threads as we like
active++;
// when creating such a thread, it is started
immediately
PooledThread newThread = new
PooledThread(this, runnable, threadName);
newThread.setDaemon(daemon);
newThread.start();
} // if(doesBlock())
} else {
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() + ".run("
+ runnable + "): pool is not empty. Reusing thread.");
// the pool is not empty, so we give out the last
returned thread to
// be equipped with the runnable
((PooledThread)pool.pop()).run(runnable);
} // if pool.isEmpty()
} // sync
} // run
/**
* The garbage collector will seldom get the chance to clear the pool unless
all pooled threads have been terminated which they
* normally dont (because of waiting for further runnables to run)? Do not know
* exactly. Anyway, therefore we expose the garbage-collector interface to be
called explicitely.
*/
public void finalize() {
if (Environment.DEBUG_LEVEL > 0)
Environment.CONSOLE.debug(toString() + ".finalize()");
// resets the max size, so no threads will come back to continue their
work
maxSize = 0;
// get a thread-safe grab onto the pool
synchronized(pool) {
// loop through the pool
Iterator iterator = pool.iterator();
while (iterator.hasNext()) {
// and mark each (waiting) thread as being finished
((PooledThread)iterator.next()).finalize();
// remove from the stack
iterator.remove();
} // while
} // sync
} // finalize
/** this method is called by the pooled threads that like to return into the
pool */
protected void returnThread(PooledThread thread) {
if (Environment.DEBUG_LEVEL > 0)
Environment.CONSOLE.debug(toString() + ".returnThread(" +
thread + ")");
// thread-safe grab onto the pool
synchronized(pool) {
// only if we have not superseded the maximum size of the pool
if (pool.size() < maxSize) {
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() +
".returnThread(" + thread + "): back into the pool.");
// push this thread to the stack
pool.push(thread);
// and awake one of the blocked threads waiting for
this
// thread to become available
pool.notify();
} else {
if (Environment.DEBUG_LEVEL > 1)
Environment.CONSOLE.debug(toString() +
".returnThread(" + thread + "): pool overflow. Destroy pooled thread.");
thread.finalize();
} // if (pool.size())
} // sync
} // returnPooledThread
} // ThreadPool
1.1 zoap/src/de/infor/ce/thread/thread.dfPackage
Index: thread.dfPackage
===================================================================
package idv7fpch1rys4sch1uxrr2;
/**
@version 2.0
@physicalPackage
@__modelType diagram
*/
class diagram {
/**
@__ref <oiref:java#Class#de.infor.ce.thread.PooledThread:oiref><oihard>
@__modelType reference
*/
class reference {
}/**
@__ref <oiref:java#Class#de.infor.ce.thread.PooledThreadLocal:oiref><oihard>
@__modelType reference
*/
class reference3 {
}/**
@__ref <oiref:java#Class#de.infor.ce.thread.ThreadPool:oiref><oihard>
@__modelType reference
*/
class reference4 {
}/**
@__ref <oiref:java#Class#de.infor.ce.thread.Environment:oiref><oihard>
@__modelType reference
*/
class reference5 {
}/**
@__ref <oiref:design#Class#id2p4gtcamcwfvycamcygzi.diagram:oiref><oihard>
@__modelType reference
@__fqn <oiref:#Package#de.infor.ce.thread.test:oiref>
*/
class reference6 {
}}/**
@__tags
@shapeType ClassDiagram
*/
class __tags {
}/**
@__options
*/
class __options {
}/**
@__positions
*/
class __positions {
}