Hi together,
as some of you may already know i have my dislikes against
ThreadQueue [1] (Hi, Larry!) see my mail [2]
a - It forks a new thread for any Runnable it processes.
b - It has an ugly busy wait loop inside.
c - The event listener for empty queue fires to often.
d - The default ThreadQueue is some kind of thread serializer.
e - The DB/WMS ThreadQueue has no public access.
Now I've written a sub class of ThreadQueue: SingleThreadQueue
(see attachment). This one deals with the issues a, b and d.
I also attached a patch against RenderingManager [3] to handle e.
The new class (to be placed in package
com.vividsolutions.jump.workbench.ui.renderer) is a drop-in
replacement for the default ThreadQueue in RenderingManager.
Not for the ThreadQueue that handles the DB/WMS layers.
Because Jon limited the number of parallel threads in default
queue to 1 I see no reason why to fork a new thread for each
Runnable it processes. Thread creation/shutdown is fairly
expensive. Instead a single background thread is started
which processes the Runnables one by one. If the thread
is idle for 30 secs it shuts itself down. If you have a lot
of (non-WMS/BB) layers this should improve performance
and save some resources. The processing itself is done
with a monitor (synchronized/wait/notify) so there is no
busy wait any more.
The DB/WMS ThreadQueue (real parallel threads) is left untouched
for the moment. Depending on my personal schedule I will send
a patch against this one too. Preliminary code with thread pooling
exists but it needs a bit more testing.
Find attached the new class and patches against RenderingManager and
the old ThreadQueue to bring it to work.
Comments are very welcome. :-)
Kind regrads,
Sascha
[1] com.vividsolutions.jump.workbench.ui.renderer.ThreadQueue
[2]
http://sourceforge.net/mailarchive/message.php?msg_name=4653389E.6000706%40intevation.de
[3] com.vividsolutions.jump.workbench.ui.renderer.RenderingManager
Index: ./src/com/vividsolutions/jump/workbench/ui/renderer/RenderingManager.java
===================================================================
RCS file:
/cvsroot/jump-pilot/openjump/src/com/vividsolutions/jump/workbench/ui/renderer/RenderingManager.java,v
retrieving revision 1.6
diff -u -r1.6 RenderingManager.java
--- ./src/com/vividsolutions/jump/workbench/ui/renderer/RenderingManager.java
22 May 2007 18:47:12 -0000 1.6
+++ ./src/com/vividsolutions/jump/workbench/ui/renderer/RenderingManager.java
24 May 2007 04:10:30 -0000
@@ -77,7 +77,7 @@
* non-database layers in parallel. In fact, it will make the GUI less
* responsive. [Jon Aquino]
*/
- private ThreadQueue defaultRendererThreadQueue = new ThreadQueue(1);
+ private ThreadQueue defaultRendererThreadQueue = new
SingleThreadQueue();
/**
* WMS and database processing are done on the server side, so allow
these
@@ -294,6 +294,10 @@
return defaultRendererThreadQueue;
}
+ public ThreadQueue getMultiRendererThreadQueue() {
+ return multiRendererThreadQueue;
+ }
+
public void dispose() {
repaintTimer.stop();
defaultRendererThreadQueue.dispose();
@@ -334,4 +338,4 @@
contentIDToRendererMap.remove(contentID);
}
-}
\ No newline at end of file
+}
Index: ./src/com/vividsolutions/jump/workbench/ui/renderer/ThreadQueue.java
===================================================================
RCS file:
/cvsroot/jump-pilot/openjump/src/com/vividsolutions/jump/workbench/ui/renderer/ThreadQueue.java,v
retrieving revision 1.1
diff -u -r1.1 ThreadQueue.java
--- ./src/com/vividsolutions/jump/workbench/ui/renderer/ThreadQueue.java
16 Jun 2005 22:50:38 -0000 1.1
+++ ./src/com/vividsolutions/jump/workbench/ui/renderer/ThreadQueue.java
24 May 2007 04:09:15 -0000
@@ -47,6 +47,10 @@
private Vector queuedRunnables = new Vector();
private int maxRunningThreads;
+ public ThreadQueue() {
+ this(1);
+ }
+
public ThreadQueue(final int maxRunningThreads) {
this.maxRunningThreads = maxRunningThreads;
}
@@ -95,7 +99,7 @@
public static interface Listener {
public void allRunningThreadsFinished();
}
- private void fireAllRunningThreadsFinished() {
+ protected void fireAllRunningThreadsFinished() {
//new ArrayList to avoid ConcurrentModificationException [Jon Aquino]
for (Iterator i = new ArrayList(listeners).iterator(); i.hasNext(); ) {
Listener listener = (Listener) i.next();
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package com.vividsolutions.jump.workbench.ui.renderer;
import java.util.LinkedList;
/**
* This special ThreadQueue uses a single thread to do all
* the rendering instead of forking a new one for each
* incomming Runnable. If the internal queue stays empty
* for TIME_TO_WAIT milli seconds the thread shuts itself down.
*
* @author Sascha L. Teichmann ([EMAIL PROTECTED])
*/
public class SingleThreadQueue
extends ThreadQueue
{
/**
* This is the time to wait before the processing thread ends.
* (30 secs)
*/
public static final long TIME_TO_WAIT = 30000L;
protected class QThread extends Thread
{
protected LinkedList queue;
public QThread() {
queue = new LinkedList();
}
public int runningThreads() {
synchronized (queue) {
return queue.size();
}
}
public void add(Runnable runnable) {
synchronized (queue) {
queue.add(runnable);
queue.notify();
}
}
public void clear() {
synchronized (queue) {
queue.clear();
}
}
public void run() {
boolean done = false;
do { // while (!done)
try {
for (;;) {
synchronized (SingleThreadQueue.this) {
if (SingleThreadQueue.this.disposed) {
done = true;
break;
}
}
Runnable runnable;
synchronized (queue) {
if (queue.isEmpty()) {
queue.wait(TIME_TO_WAIT);
if (queue.isEmpty()) {
synchronized (SingleThreadQueue.this) {
// This may look odd but it guarantees that
// no add() is done while checking for emptiness.
if (queue.isEmpty())
break;
}
}
}
runnable = (Runnable)queue.remove();
if (runnable == null)
break;
} // synchronized queue
try {
runnable.run();
}
catch (Exception e) {
e.printStackTrace();
}
} // for (;;)
}
catch (InterruptedException ie) {
done = true;
}
finally {
synchronized (queue) {
if (queue.isEmpty())
done = true;
}
synchronized (SingleThreadQueue.this) {
SingleThreadQueue.this.thread = null;
}
}
}
while (!done);
SingleThreadQueue.this.fireAllRunningThreadsFinished();
}
} // class QThread
protected boolean disposed;
protected QThread thread;
public SingleThreadQueue() {
}
public synchronized void clear() {
if (thread != null)
thread.clear();
}
public synchronized void add(Runnable runnable) {
if (disposed)
return;
if (thread == null) {
thread = new QThread();
thread.setDaemon(true);
thread.start();
}
thread.add(runnable);
}
public synchronized int runningThreads() {
return thread == null ? 0 : thread.runningThreads();
}
public synchronized void dispose() {
clear();
disposed = true;
}
}
// end of file
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel