Look, Ma: Running SwingWorkers...

See ma? They're running there...

Screenshot of test application

So continuing my last post I decided to build an easy-to-use SwingWorkerManager to monitor how my SwingWorkers run in the wild.

I've built a SwingWorkerManager.getInstance() singleton to which I "submit( SwingWorker )" for execution. The SwingWorkerManager has a little ListModel that keeps track of the last executed SwingWorkers (by adding PropertyChangeListeners to them) and monitors their activity.

Apart of this ListModel the SwingWorkerManager can create also a ListCellRenderer to better visualize SwingWorker progress.

Source code (LGPL'ed) is available. Of course you can also run this little Java WebStart demo (note: JDK 5.0 required). Instructions for using the SwingWorkerManager are included in the javadoc documentation.

Sizing the pool...

So as I said before this SwingWorkerManager uses an internal thread pool to execute SwingWorkers. As Jeffrey wisely pointed out in his comment, the size of the pool should depend on the number of available processors NCPU in the environment (that is, it should be a linear function of NCPU=Runtime.getRuntime().availableProcessors()). So, continuing our previous discussion:

M = F \* NCPU < N 

Where M is the number of threads in the pool, F is a constant, NCPU is the number of CPUs in the system and N is the number of scheduled tasks.

Since usually many threads are just waiting for I/O it would be a waste of time to set F=1 (since then many CPUs would be just hanging around waiting for I/O). So I think a good F value could be around 3. That way we'll kick those lazy CPUs. You know, CPU speeds are very high nowadays, and CPU cycles are probably cheaper than any other kind of resource.

So let's assume F=3 is a good bet. Are we missing something? Well, er.. what about those slow ones?

Come on, you lazy one, hurry up, get out of my way...

Assume you're downloading a 10 Gb file from somewhere. You, of course, want to use a SwingWorker for that. But that's gonna take quite some time. And we're using a fixed thread pool, right? So that task is going to reduce the size of our fixed thread pool (and, thus, reduce the responsiveness of our GUI).

How could we handle this? Well, two solutions come to mind...

  • a) Increase M slightly to make room for these slow ones.
  • b) Use another fixed thread pool to schedule these very long-running, very time-consuming slow processes.
  • c) Use one of the above and provide a timeout setting for scheduling tasks. That way those tasks that have not finished before the given timeout value would be automatically interrupted.

The two first ones are not difficult to implement...

Solution a) would require this value for M:

M = F \* NCPU + SLOW < N 

Where SLOW is a fixed value that approximates the number of simultaneous slow processes you think may be running in your application.

And solution b) would require adding a new fixed thread pool (of size, say, SLOW) and a new method (say "submitSlowTask( SwingWorker )") that schedules things into this new fixed thread pool.

The third solution won't be too difficult to implement, either (by slightly increasing M to allocate timeout watcher SwingWorkers).

What do you think? Which one do you like best? Come on, give me a hand here! ;-)

The wonderfully complex world of task scheduling

Many Task Scheduling algorithms are NP hard problems. The SwingWorkerManager presented here implements a simple FIFO (First In-First Out) solution to scheduling SwingWorkers in a set of threads.

SwingWorkerManager may be a good way to experiment different task scheduling algorithms (say, in a Computer Science classroom), but I think a FIFO is good enough for me. And, of course, I can watch my SwingWorkers running. See ma? I hope it's good for you too (and if not, then just complain here! ;-)).

Please let me know of any improvements or bugs.

Happy swinging,
Antonio

Comentarios:

I'd say a combo of a & b... A pool of slow ones using the (f \* ncpu) then possible a fast pool from that that can be interupted and if a submition gets interupted a few times it gets submitted to the slow pool? fast = z, where z is some value > 0 slow = (f \* ncpu) - fast M = fast + slow < N And I'd assume if you had a slow pool, and if nothing was being processed by them you could just pass things off to those for processing as well just to free up the fast pool faster. Just my thoughts! Also, awesome job! =)

Enviado por Jeffrey Olson en enero 19, 2006 a las 02:03 PM CET #

Reposting this with formating, Antonio it says html syntax is off? Yet it requires html breaks to get new lines, is that a bug or is that normal? Also, the bloody math thing is still messed up!

I'd say a combo of a & b... A pool of slow ones using the (f \* ncpu) then possible a fast pool from that that can be interupted and if a submition gets interupted a few times it gets submitted to the slow pool?

fast = z, where z is some value > 0
slow = (f \* ncpu) - fast
M = fast + slow < N

And I'd assume if you had a slow pool, and if nothing was being processed by them you could just pass things off to those for processing as well just to free up the fast pool faster. Just my thoughts!

Also, awesome job! =)

Enviado por Jeffrey Olson en enero 19, 2006 a las 02:09 PM CET #

Hi Jeffrey,
Yes, I'm aware of the bugs in the comments. I've already posted some bugs reports to the blog guys.
That's a nice idea of yours. Maybe it's a good idea to have two different lanes for scheduling. A fast one (so small simple tasks get executed faster and a long one, probably with a lower thread priority). I'll think of it.
And I think that being able to cancel SwingWorkers from within the list (or Table?) may be a good enhancement as well. (And probably approximating a possible "time to finish" value too).
I think that SwingWorkerManager may be a good companion for an event bus.
Thanks for your tips,
Antonio

Enviado por Antonio en enero 20, 2006 a las 03:12 AM CET #

And, just brain-storming even more (this is weird, I think I'm thinking too much) maybe a Coffman-Graham algorithm is a good idea for scheduling. This algorithm is used for graph drawing too (layering acyclic graphs) so maybe I can benefit of it afterwards.

Thanks again,
Antonio

Enviado por Antonio en enero 20, 2006 a las 03:17 AM CET #

This is great. I was looking for a component like this, but I don't have time to write one. Do you know if there are other such components out there that I can look at? I need something that shows progress bars for multiple threads kinda like the Eclipse Progress panel.

Enviado por Trey en enero 25, 2006 a las 04:45 AM CET #

Hi,
Oh, NetBeans has components for visually displaying running tasks, too.
On the other hand I have not the faintest idea about what the Eclipse Progress panel looks like. (I don't use Eclipse, sorry).
Cheers,
Antonio

Enviado por Antonio en enero 27, 2006 a las 02:32 AM CET #

Enviar un comentario:
Los comentarios han sido deshabilitados.
About

swinger

Search

Archives
« abril 2014
lunmarmiéjueviesábdom
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Hoy