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