Hi Larry,

the magic word here is 'critical region'
Have a look a the finally block.
Assume the setRunningThreads(getRunningThreads() - 1) call
was executed and the counter went to zero. This is done in Thread A.
And now directly comes a context switch to your code
in Thread B. Your if statement thinks that there are no
jobs any more -> Your loop ends. Context switch back to Thread A.
Now the processQueue() call is executed and potentially a
new thread is started because the queue is not empty.
Counter is zero but queue not empty.
Thread programming is delicate, isn't it?

- Sascha


Larry Becker schrieb:
> Hi Sascha,
> 
>   I do not see the difference.  It seems to me that when a task is
> finished, the runningThreads count is decremented as in:
> 
>                 try {
>                     runnable.run();
>                 } finally {
>                     setRunningThreads(getRunningThreads() - 1);
>                     processQueue();
>                 }
> 
> So it would seem to me that when the count reaches zero that there are
> no more jobs.
> 
> regards,
> Larry
> 
> On 5/30/07, Sascha L. Teichmann <[EMAIL PROTECTED]> wrote:
>> Hi Larry,
>>
>> The method is named runningThreads(). This was my
>> mistake. I will add add get getRunningThreads() to
>> reestablish compatibility. Thanks for this hint.
>>
>> BTW: You're code:
>>
>> while (threadQueue.getRunningThreads() > 0) Thread.sleep(200);
>>
>> tests if there are running _threads_ left. This do not tell
>> you if there are _jobs_ to to! What you really want to know
>> is when the last job is done. See the difference?
>>
>> The new RenderingManager will have a new method to archive
>> this. It will switch the thread queue to single threaded mode
>> and enqueues a special Runnable at the end. Then the calling
>> thread is lock with a monitor. If the special Runnable is
>> executed the monitor is unlocked and the calling thread continues.
>> This is what you want.
>>
>> Switching to single thread mode has the advantage to keep
>> the correct z order of the layers. This is essential for
>> printing because you don't want to have any internal repaint()
>> operations. This causes overdraw. If you render to bitmap this
>> might be okay, but if you want to send the vector information
>> to the Graphics2D of the output driver this is not a good idea.
>>
>> Kind regards,
>>   Sascha
>>
>>
>> Larry Becker schrieb:
>>> It doesn't look like I'm going to have time to test the new
>>> ThreadQueue anytime soon.  I did plug it in long enough to determine
>>> that it broke my code that called getRunningThreads() since that
>>> method is no longer present.  I didn't have time to  look for the new
>>> method that I should use instead.  I should be able to get back to it
>>> in a couple of weeks (I'm instructing a class in our software next
>>> week).
>>>
>>> regards,
>>> Larry
>>>
>>> On 5/30/07, Michaël Michaud <[EMAIL PROTECTED]> wrote:
>>>>> Hei Saschachaël
>>>>>
>>>>> i got positive feedback from my colleaque on the changes of the
>>>>> threading stuff.
>>>>> If Michael aggrees too, you can commit
>>>>>
>>>>>
>>>> As far as I'm concerned, I am really pleased to see Sascha's
>>>> contribution to the core.
>>>> OJ really needs contributions from skilled programmers :-) .
>>>>
>>>> Michaël
>>>>
>>>>> stefan
>>>>>
>>>>> Sascha L. Teichmann schrieb:
>>>>>
>>>>>
>>>>>> Hi!
>>>>>>
>>>>>> Stefan Steiniger schrieb:
>>>>>>
>>>>>>
>>>>>>> Similar to Landon I have never touched threading nor heared any lectures
>>>>>>> or read books on it. Thus .. i dont know if it turns out to be good or 
>>>>>>> bad.
>>>>>>> But i know that making things more clean is good objective. Thus, i
>>>>>>> support the changes. It would be good when we finally change the code,
>>>>>>> that you also put into the code some docs or references where you
>>>>>>> outline why somethings has changed. (actually I currently would opt to
>>>>>>> leave the old code as comment and not to remove entirely)
>>>>>>>
>>>>>>>
>>>>>> The ThreadQueue is JavaDoc'ed but I can add some
>>>>>> design notes as well. Keeping old things as comments negates
>>>>>> the existence of version control systems.
>>>>>> CVS is exactly the time machine you for this.
>>>>>> As I pointed out earlier having a ChangeLog would
>>>>>> be nice to document motivations and backgrounds for a change. Simply
>>>>>> generating a ChangeLog out of the commit messages is convenient but
>>>>>> it does not uncover the true potential of such a 'log' file.
>>>>>>
>>>>>>
>>>>>>
>>>>>>> Due to my lack of knowledge i forwarded your email to a colleague who
>>>>>>> developed a web-service based on JUMP (which runs on a server, see [1]),
>>>>>>> an ajax client and recently did some multiprocessor experiments for the
>>>>>>> web-services processing.
>>>>>>>
>>>>>>>
>>>>>> I look forward to his comments.
>>>>>>
>>>>>>
>>>>>>
>>>>>>> I hope 1) he will look on your proposal and 2) you can wait some days
>>>>>>> until he, Larry and Michael got an opinion.
>>>>>>>
>>>>>>>
>>>>>> @Michael: You ask what to change. For the moment just replace
>>>>>> ThreadQueue.java with one I've sent last. The first patches
>>>>>> are addressing the problem with ThreadQueue limited to one
>>>>>> Thread at a time (defaultRenderingThreadQueue in RenderingManger).
>>>>>> You can apply these patches too, but they are not needed any
>>>>>> longer. With next patch I'll send the this second thread queue
>>>>>> will be removed from RenderingManager entirely.
>>>>>>
>>>>>> What to test? Doing your day-to-day is the best thing
>>>>>> you can do. The most important thing is that the new one
>>>>>> behaves exactly like the old one. The magic word is compatibility.
>>>>>> I don't want to break the show. Use plug-ins, use many layers,
>>>>>> use less layer, use db and WMS layers. Do all the fancy stuff
>>>>>> you like to do. If the OJ freezes or something other looks odd
>>>>>> just tell me. :-)
>>>>>>
>>>>>> - Sascha
>>>>>>
>>>>>>
>>>>>>
>>>>>>> Michaël Michaud schrieb:
>>>>>>>
>>>>>>>
>>>>>>>> Sascha L. Teichmann a écrit :
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>> Really back to topic:
>>>>>>>>>
>>>>>>>>> Find attached a replacement for ThreadQueue [1].
>>>>>>>>> To use it just overwrite the original one.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>> Hi Sascha :
>>>>>>>>
>>>>>>>> I think that trying to have a cleaner and more simple code is an
>>>>>>>> excellent goal, and I'd like to help, but I'm not sure I can understand
>>>>>>>> all these thread issues.
>>>>>>>> If you tell me exactly which classes I must replace (on ly ThreadQueue
>>>>>>>> or also the pieces of code from your previous mail) and what kind of
>>>>>>>> tests I should do (rendering different kind of layers ? mixing 
>>>>>>>> different
>>>>>>>> kind of layers), I'll try to make some more tests on my desktop.
>>>>>>>>
>>>>>>>> Thanks, for the hard work
>>>>>>>>
>>>>>>>> Michaël
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>> This one works for the real parallel case of
>>>>>>>>> layer rendering too. Each time a thread finished
>>>>>>>>> executing its Runnable it looks into the queue
>>>>>>>>> if they are more jobs to do. This prevents unnecessary
>>>>>>>>> thread creations/shutdowns. If the queue is empty
>>>>>>>>> the worker thread is kept alive for 5 seconds waiting
>>>>>>>>> for new jobs. This results in a kind of thread pooling.
>>>>>>>>>
>>>>>>>>> @Larry: I've isolated my implementation and the OJ
>>>>>>>>> ThreadQueue and done a synthetic benchmark with a
>>>>>>>>> larger number of jobs (10,000+). My implementation
>>>>>>>>> works about two orders faster than the OJ one.
>>>>>>>>> But this is of little meaning because OJ only
>>>>>>>>> has to handle a number of jobs equal the number
>>>>>>>>> of layers. This will hardly hit 10,000+ ;-)
>>>>>>>>> But again: My mission is improve the structure not
>>>>>>>>> primarily the speed.
>>>>>>>>>
>>>>>>>>> I've tested the new ThreadQueue to some extent but
>>>>>>>>> I'am male(tm) after all ... potentially making mistakes.
>>>>>>>>> It would be very kind if someone test it too.
>>>>>>>>>
>>>>>>>>> My next step will be some clean up in the RenderingManager [2].
>>>>>>>>> I'am not sure that it is really needed to have two ThreadQueues
>>>>>>>>> there. The effect of the single tread one can be easily
>>>>>>>>> simulated with a data structure like the RunnableArrayList which
>>>>>>>>> I've posted already.
>>>>>>>>>
>>>>>>>>> Any comments?
>>>>>>>>>
>>>>>>>>> Yours,
>>>>>>>>> Sascha
>>>>>>>>>
>>>>>>>>> [1] com.vividsolutions.jump.workbench.ui.renderer.ThreadQueue
>>>>>>>>> [2] com.vividsolutions.jump.workbench.ui.renderer.RenderingManager
>>>>>>>>>
>>>>>>>>> Sunburned Surveyor schrieb:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>> Sascha,
>>>>>>>>>>
>>>>>>>>>> Please accept my sincerest aopologies. I'm afriad my American
>>>>>>>>>> ignorance of other cultures is more than just a little obvious at
>>>>>>>>>> times.
>>>>>>>>>>
>>>>>>>>>> I believe I have made the same mistake with Jan. :]
>>>>>>>>>>
>>>>>>>>>> Please be patient with me as I learn the details of cultures across
>>>>>>>>>> the Pacific and Atalantic Oceans!
>>>>>>>>>>
>>>>>>>>>> The Sunburned Surveyor
>>>>>>>>>>
>>>>>>>>>> On 5/24/07, Sascha L. Teichmann <[EMAIL PROTECTED]> wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>> TNX, but for the records 'he' would be more suited in my case.
>>>>>>>>>>>
>>>>>>>>>>> 'Sascha' is basically a Russian term of endearment for the
>>>>>>>>>>> boys name 'Alexander' but it's also used as a girls name.
>>>>>>>>>>>
>>>>>>>>>>> BTW: 'Jan' is a girls name in the US too, isn't? ;-)
>>>>>>>>>>>
>>>>>>>>>>> - Sascha
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> Sunburned Surveyor schrieb:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>> Sascha and Larry,
>>>>>>>>>>>>
>>>>>>>>>>>> I must admit that I am way over my head here. I haven't done much
>>>>>>>>>>>> thread programming in Java. (Hopefully Stefan has!)
>>>>>>>>>>>>
>>>>>>>>>>>> Sascha wrote: "My primary goal is to simplify the
>>>>>>>>>>>> threading code to make it more reliable in terms of time."
>>>>>>>>>>>>
>>>>>>>>>>>> This seems like an admirable goal to me. If Larry, or a similar
>>>>>>>>>>>> programmer of his experience, agrees that this changes would be
>>>>>>>>>>>> beneficial, I say we give Sascha a shot at it. It sounds like she 
>>>>>>>>>>>> has
>>>>>>>>>>>> considered her changes carefully.
>>>>>>>>>>>>
>>>>>>>>>>>> Just my two cents.
>>>>>>>>>>>>
>>>>>>>>>>>> The Sunburned Surveyor
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On 5/24/07, Sascha L. Teichmann <[EMAIL PROTECTED]> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> Hi Larry,
>>>>>>>>>>>>>
>>>>>>>>>>>>> short answer first: No, I don't have any benchmarks, yet.
>>>>>>>>>>>>>
>>>>>>>>>>>>> The long answer: My primary goal is to simplify the
>>>>>>>>>>>>> threading code to make it more reliable in terms of time.
>>>>>>>>>>>>> Gaining performance improvements would be a neat side effect.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Background: Multi-threading may be fine for slow layers
>>>>>>>>>>>>> which arrives later on the screen but for exporting
>>>>>>>>>>>>> the data (to print/layout e.g) it would be nice to have
>>>>>>>>>>>>> them arriving one after the other.
>>>>>>>>>>>>>
>>>>>>>>>>>>> My final goal is to have a simple switch between the normal
>>>>>>>>>>>>> and the serial mode. To archive that I try to carefully
>>>>>>>>>>>>> refactor the system doing little patches step by step
>>>>>>>>>>>>> not to break it. Refactoring the ThreadQueue with it's
>>>>>>>>>>>>> 'flaws' seems a to be a good starting point to me.
>>>>>>>>>>>>>
>>>>>>>>>>>>> One reason for this change is the fact that you are able
>>>>>>>>>>>>> to figure out if the default thread runs empty. But there
>>>>>>>>>>>>> is no way to figure out when the last thread ends. That
>>>>>>>>>>>>> are different things. A mechanism for this is planned.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Sorry, if I've shadowed my true intentions to much. Maybe
>>>>>>>>>>>>> I should discuss more before I send patches.  ;-)
>>>>>>>>>>>>>
>>>>>>>>>>>>> Back to the technical side:
>>>>>>>>>>>>>
>>>>>>>>>>>>> The patch needs some testing but I don't expect too much
>>>>>>>>>>>>> performance improvement.
>>>>>>>>>>>>>
>>>>>>>>>>>>> A less intrusive alternative to bind the Runnables that go to the
>>>>>>>>>>>>> default ThreadQueue into one thread is to create a container
>>>>>>>>>>>>> which self is Runnable (see e.g. RunnableArrayList attached)
>>>>>>>>>>>>> and put them into an instance of this class.
>>>>>>>>>>>>> This container is put into multiRendererThreadQueue as a Runnable.
>>>>>>>>>>>>> With this modification the defaultRendererThreadQueue can
>>>>>>>>>>>>> be removed (multiRendererThreadQueue renamed to
>>>>>>>>>>>>> defaultRendererThreadQueue). Only an idea ... I'm in discussion
>>>>>>>>>>>>> mode now. ;-)
>>>>>>>>>>>>>
>>>>>>>>>>>>> - Sascha
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Larry Becker schrieb:
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>> Hi Sascha,
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I read your comments and look at your code with interest.  It 
>>>>>>>>>>>>>> appears
>>>>>>>>>>>>>> to be an improved ThreadQueue implementation, but will require a 
>>>>>>>>>>>>>> lot of
>>>>>>>>>>>>>> testing to verify.  Before I invest this time, I would like to 
>>>>>>>>>>>>>> know what
>>>>>>>>>>>>>> problem it is solving.  I see your dislikes a - e, but these are 
>>>>>>>>>>>>>> not
>>>>>>>>>>>>>> really problems, only architectural critiques.  Have you done any
>>>>>>>>>>>>>> benchmarks that show that the new SingleThreadQueue speeds up
>>>>>>>>>>>>>> rendering?  Your logical argument that it should be more 
>>>>>>>>>>>>>> efficient  is
>>>>>>>>>>>>>> persuasive,  but  I have been surprised by Java before.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> respectfully,
>>>>>>>>>>>>>> Larry Becker
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On 5/23/07, *Sascha L. Teichmann* <[EMAIL PROTECTED]
>>>>>>>>>>>>>> <mailto:[EMAIL PROTECTED]>> wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>   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
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> ------------------------------------------------------------------------
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> /*
>>>>>>>>>>>>>> * The Unified Mapping Platform (JUMP) is an extensible, 
>>>>>>>>>>>>>> interactive GUI
>>>>>>>>>>>>>> * for visualizing and manipulating spatial features with 
>>>>>>>>>>>>>> geometry and attributes.
>>>>>>>>>>>>>> *
>>>>>>>>>>>>>> * Copyright (C) 2003 Vivid Solutions
>>>>>>>>>>>>>> * Copyright (C) 2007 Intevation GmbH
>>>>>>>>>>>>>> *
>>>>>>>>>>>>>> * 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.
>>>>>>>>>>>>>> *
>>>>>>>>>>>>>> * Suite #1A
>>>>>>>>>>>>>> * 2328 Government Street
>>>>>>>>>>>>>> * Victoria BC  V8T 5G5
>>>>>>>>>>>>>> * Canada
>>>>>>>>>>>>>> *
>>>>>>>>>>>>>> * (250)385-6040
>>>>>>>>>>>>>> * www.vividsolutions.com
>>>>>>>>>>>>>> */
>>>>>>>>>>>>>> package com.vividsolutions.jump.workbench.ui.renderer;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> import java.util.LinkedList;
>>>>>>>>>>>>>> import java.util.ArrayList;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> /**
>>>>>>>>>>>>>> * This thread queue executes at maximum N Runnables in parallel
>>>>>>>>>>>>>> * were N is a given number of worker threads that should be used.
>>>>>>>>>>>>>> * If N threads are running and busy each further incoming
>>>>>>>>>>>>>> * Runnable is queued until one of the threads has finished its 
>>>>>>>>>>>>>> current job.
>>>>>>>>>>>>>> * If a worker thread becomes idle (no more job in the queue)
>>>>>>>>>>>>>> * it is hold alive for 5 seconds. If during this period of time
>>>>>>>>>>>>>> * no new Runnable is enqueued the worker thread dies.
>>>>>>>>>>>>>> *
>>>>>>>>>>>>>> * @author Sascha L. Teichmann ([EMAIL PROTECTED])
>>>>>>>>>>>>>> */
>>>>>>>>>>>>>> public class ThreadQueue
>>>>>>>>>>>>>> {
>>>>>>>>>>>>>>      /** The time a worker thread stays alive if idle */
>>>>>>>>>>>>>>      public static final long WORKER_STAY_ALIVE_TIME = 5000L;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * Worker thread. Fetches Runnable from the surrounding
>>>>>>>>>>>>>>       * ThreadQueue instance.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      protected class Worker
>>>>>>>>>>>>>>      extends         Thread
>>>>>>>>>>>>>>      {
>>>>>>>>>>>>>>              public void run() {
>>>>>>>>>>>>>>                      try {
>>>>>>>>>>>>>>                              for (;;) {
>>>>>>>>>>>>>>                                      Runnable runnable;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>                                      synchronized 
>>>>>>>>>>>>>> (queuedRunnables) {
>>>>>>>>>>>>>>                                              if 
>>>>>>>>>>>>>> (queuedRunnables.isEmpty()) {
>>>>>>>>>>>>>>                                                      
>>>>>>>>>>>>>> ++waitingThreads;
>>>>>>>>>>>>>>                                                      try {
>>>>>>>>>>>>>>                                                              
>>>>>>>>>>>>>> queuedRunnables.wait(WORKER_STAY_ALIVE_TIME);
>>>>>>>>>>>>>>                                                      }
>>>>>>>>>>>>>>                                                      catch 
>>>>>>>>>>>>>> (InterruptedException ie) {
>>>>>>>>>>>>>>                                                      }
>>>>>>>>>>>>>>                                                      finally {
>>>>>>>>>>>>>>                                                              
>>>>>>>>>>>>>> --waitingThreads;
>>>>>>>>>>>>>>                                                      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>                                                      // if still 
>>>>>>>>>>>>>> empty -> die!
>>>>>>>>>>>>>>                                                      if 
>>>>>>>>>>>>>> (queuedRunnables.isEmpty())
>>>>>>>>>>>>>>                                                              
>>>>>>>>>>>>>> break;
>>>>>>>>>>>>>>                                              }
>>>>>>>>>>>>>>                                              if (disposed)
>>>>>>>>>>>>>>                                                      break;
>>>>>>>>>>>>>>                                              runnable = 
>>>>>>>>>>>>>> (Runnable)queuedRunnables.remove();
>>>>>>>>>>>>>>                                      } // synchronized 
>>>>>>>>>>>>>> queuedRunnables
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>                                      try {
>>>>>>>>>>>>>>                                              runnable.run();
>>>>>>>>>>>>>>                                      }
>>>>>>>>>>>>>>                                      catch (Exception e) {
>>>>>>>>>>>>>>                                              e.printStackTrace();
>>>>>>>>>>>>>>                                      }
>>>>>>>>>>>>>>                              } // for (;;)
>>>>>>>>>>>>>>                      }
>>>>>>>>>>>>>>                      finally { // guarantee that counter goes 
>>>>>>>>>>>>>> down
>>>>>>>>>>>>>>                              boolean allRunningThreadsFinished;
>>>>>>>>>>>>>>                              synchronized (runningThreads) {
>>>>>>>>>>>>>>                                      allRunningThreadsFinished = 
>>>>>>>>>>>>>> --runningThreads[0] == 0;
>>>>>>>>>>>>>>                              }
>>>>>>>>>>>>>>                              if (allRunningThreadsFinished)
>>>>>>>>>>>>>>                                      
>>>>>>>>>>>>>> fireAllRunningThreadsFinished();
>>>>>>>>>>>>>>                      }
>>>>>>>>>>>>>>              }
>>>>>>>>>>>>>>      } // class Worker
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * If the number of running threads goes down to zero
>>>>>>>>>>>>>>       * implementations of this interface are able to be 
>>>>>>>>>>>>>> informed.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public interface Listener {
>>>>>>>>>>>>>>              void allRunningThreadsFinished();
>>>>>>>>>>>>>>      } // interface Listener
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /** Number of running threads */
>>>>>>>>>>>>>>      protected int [] runningThreads = new int[1];
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /** max. Number of threads running parallel */
>>>>>>>>>>>>>>      protected int maxRunningThreads;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /** Number of threads that are currently idle */
>>>>>>>>>>>>>>      protected int waitingThreads;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /** The queue of Runnables jobs waiting to be run */
>>>>>>>>>>>>>>      protected LinkedList queuedRunnables;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /** Singals that the ThreadQueue is going to quit */
>>>>>>>>>>>>>>      protected boolean disposed;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /** List of Listeners */
>>>>>>>>>>>>>>      protected ArrayList listeners = new ArrayList();
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * Creates a ThreadQueue with one worker thread.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public ThreadQueue() {
>>>>>>>>>>>>>>              this(1);
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /** Creates a ThreadQueue with a given number of worker 
>>>>>>>>>>>>>> threads.
>>>>>>>>>>>>>>       * @param maxRunningThreads the max. number of threads to 
>>>>>>>>>>>>>> be run parallel.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public ThreadQueue(int maxRunningThreads) {
>>>>>>>>>>>>>>              this.maxRunningThreads = Math.max(1, 
>>>>>>>>>>>>>> maxRunningThreads);
>>>>>>>>>>>>>>              queuedRunnables = new LinkedList();
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * Adds a Listener to this ThreadQueue.
>>>>>>>>>>>>>>       * @param listener the listener to add.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public synchronized void add(Listener listener) {
>>>>>>>>>>>>>>              if (listener != null)
>>>>>>>>>>>>>>                      listeners.add(listener);
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * Removes a Listener from this ThreadQueue.
>>>>>>>>>>>>>>       * @param listener the listener to be removed.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public synchronized void remove(Listener listener) {
>>>>>>>>>>>>>>              if (listener != null)
>>>>>>>>>>>>>>                      listeners.add(listener);
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * Informs Listeners of the fact that the number of running 
>>>>>>>>>>>>>> threads
>>>>>>>>>>>>>>       * went to zero.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      protected void fireAllRunningThreadsFinished() {
>>>>>>>>>>>>>>              ArrayList copy;
>>>>>>>>>>>>>>              synchronized (this) { copy = new 
>>>>>>>>>>>>>> ArrayList(listeners); }
>>>>>>>>>>>>>>              for (int i = copy.size()-1; i >= 0; --i)
>>>>>>>>>>>>>>                      
>>>>>>>>>>>>>> ((Listener)copy.get(i)).allRunningThreadsFinished();
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * The number of currently running worker threads.
>>>>>>>>>>>>>>       * @return number of currently running worker threads.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public int runningThreads() {
>>>>>>>>>>>>>>              synchronized (runningThreads) {
>>>>>>>>>>>>>>                      return runningThreads[0];
>>>>>>>>>>>>>>              }
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * The number of currently waiting Runnables.
>>>>>>>>>>>>>>       * @return number of currently waiting Runnables.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public int waitingRunnables() {
>>>>>>>>>>>>>>              synchronized (runningThreads) {
>>>>>>>>>>>>>>                      return queuedRunnables.size();
>>>>>>>>>>>>>>              }
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * The number of currently idle worker threads.
>>>>>>>>>>>>>>       * @return number of currently idle worker threads.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public int waitingThreads() {
>>>>>>>>>>>>>>              synchronized (queuedRunnables) {
>>>>>>>>>>>>>>                      return waitingThreads;
>>>>>>>>>>>>>>              }
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * Adds a Runnables to the queue. It will be run in one
>>>>>>>>>>>>>>       * of the worker threads.
>>>>>>>>>>>>>>       * @param runnable The Runnables to add
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public void add(Runnable runnable) {
>>>>>>>>>>>>>>              int waiting;
>>>>>>>>>>>>>>              synchronized (queuedRunnables) {
>>>>>>>>>>>>>>                      if (disposed)
>>>>>>>>>>>>>>                              return;
>>>>>>>>>>>>>>                      waiting = waitingThreads;
>>>>>>>>>>>>>>                      queuedRunnables.add(runnable);
>>>>>>>>>>>>>>                      queuedRunnables.notify();
>>>>>>>>>>>>>>              }  // synchronized (queuedRunnables)
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>              synchronized (runningThreads) {
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>                      // if waitingThreads == 1 then
>>>>>>>>>>>>>>                      // the queuedRunnables.notify() should have 
>>>>>>>>>>>>>> waked it up.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>                      if (waitingThreads < 2 && runningThreads[0] 
>>>>>>>>>>>>>> < maxRunningThreads) {
>>>>>>>>>>>>>>                              ++runningThreads[0];
>>>>>>>>>>>>>>                              Worker w = new Worker();
>>>>>>>>>>>>>>                              w.setDaemon(true);
>>>>>>>>>>>>>>                              w.start();
>>>>>>>>>>>>>>                      }
>>>>>>>>>>>>>>              } // synchronized (runningThreads)
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * Empties the queue of waiting Runnables.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public void clear() {
>>>>>>>>>>>>>>              synchronized (queuedRunnables) {
>>>>>>>>>>>>>>                      queuedRunnables.clear();
>>>>>>>>>>>>>>              }
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>      /**
>>>>>>>>>>>>>>       * Shuts down the ThreadQueue.
>>>>>>>>>>>>>>       */
>>>>>>>>>>>>>>      public void dispose() {
>>>>>>>>>>>>>>              synchronized (queuedRunnables) {
>>>>>>>>>>>>>>                      disposed = true;
>>>>>>>>>>>>>>                      queuedRunnables.clear();
>>>>>>>>>>>>>>                      // wakeup idle threads
>>>>>>>>>>>>>>                      queuedRunnables.notifyAll();
>>>>>>>>>>>>>>              }
>>>>>>>>>>>>>>              synchronized (this) {
>>>>>>>>>>>>>>                      listeners.clear();
>>>>>>>>>>>>>>              }
>>>>>>>>>>>>>>      }
>>>>>>>>>>>>>> }
>>>>>>>>>>>>>> // 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
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>> -------------------------------------------------------------------------
>>>>>>>> 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
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>> -------------------------------------------------------------------------
>>>>>>> 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
>>>>>>>
>>>>>>>
>>>>>> -------------------------------------------------------------------------
>>>>>> 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
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>> -------------------------------------------------------------------------
>>>>> 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
>>>>>
>>>>>
>>>>>
>>>>>
>>>> -------------------------------------------------------------------------
>>>> 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
>>>>
>>>
>> -------------------------------------------------------------------------
>> 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
>>
> 
> 

-------------------------------------------------------------------------
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

Reply via email to