Parallel is a container task - it can contain other Ant tasks. Each nested task within the parallel task will be executed in its own thread.
Attribute | Description | Required |
threadCount | Maximum numbers of thread to use. | No |
threadsPerProcessor | Maximum number of threads to use per available processor (Requires JDK 1.4) | No, defers to threadCount |
pollInterval | Currently has no effect | No, default is 1000 |
timeout | Number of milliseconds before execution is terminated | No |
failonany | If any of the nested tasks fails, execution of the task completes at that point without waiting for any other tasks to complete. | No |
Parallel tasks have a number of uses in an Ant build file including:
Care must be taken when using multithreading to ensure the tasks within the
threads do not interact. For example, two javac compile tasks which write
classes into the same destination directory may interact where one tries to
read a class for dependency information while the other task is writing the
class file. Be sure to avoid these types of interactions within a
<parallel>
task
Any valid Ant task may be embedded within a parallel task, including other parallel tasks.
Note that while the tasks within the parallel task are being run, the main thread will be blocked waiting for all the child threads to complete. If execution is terminated by a timeout or a nested task failure when the failonany flag is set, the parallel task will complete without waiting for other nested tasks to complete in other threads.
If any of the tasks within the <parallel>
task fails and failonany is
not set, the remaining tasks in other threads will continue to run until
all threads have completed. In this situation, the parallel task will also fail.
The parallel task may be combined with the sequential task to define sequences of tasks to be executed on each thread within the parallel block
The threadCount attribute can be used to place a maximum number of available threads for the execution. When not present all child tasks will be executed at once. When present then the maximum number of concurrently executing tasks will not exceed the number of threads specified. Furthermore, each task will be started in the order they are given. But no guarantee is made as to the speed of execution or the order of completion of the tasks, only that each will be started before the next.
If you are using J2RE 1.4 or later you can also use the threadsPerProcessor and the number of available threads will be the stated multiple of the number of processors (there is no affinity to a particular processor however). This will override the value in threadCount. If threadsPerProcessor is specified using any version prior to 1.4 then the value in threadCount will be used as is.
When using threadCount and threadsPerProcessor care should be taken to ensure that the build does not deadlock. This can be caused by tasks such as waitFor taking up all available threads before the tasks that would unlock the waitfor would occur. This is not a repalcement for Java Language level thread semantics and is best used for "embarassingly parallel" tasks.
The parallel task supports a <daemons>
nested element. This is a list of tasks
which are to be run in parallel daemon threads. The parallel task will not wait for
these tasks to complete. Being daemon threads, however, they will not prevent Ant from
completing, whereupon the threads are terminated. Failures in daemon threads which
occur before the parallel task itself finishes will be reported and can cause
parallel to throw an exception. Failures which occur after parallel has completed are not
reported.
Daemon tasks can be used, for example, to start test servers which might not be easily
terminated from Ant. By using <daemons>
such servers do not halt the build.
<parallel> <wlrun ... > <sequential> <sleep seconds="30"/> <junit ... > <wlstop/> </sequential> </parallel>
This example represents a typical pattern for testing a server application. In one thread the server is started (the wlrun task). The other thread consists of a three tasks which are performed in sequence. The sleep task is used to give the server time to come up. Another task which is capable of validating that the server is available could be used in place of the sleep task. The test harness is then run. Once the tests are complete, the server is stopped (using wlstop in this example), allowing both threads to complete. The parallel task will also complete at this time and the build will then continue.
<parallel> <javac ...> <!-- compiler servlet code --> <wljspc ...> <!-- precompile JSPs --> </parallel>
This example shows two independent tasks being run to achieve better resource utilization during the build. In this instance, some servlets are being compiled in one thead and a set of JSPs is being precompiled in another. As noted above, you need to be careful that the two tasks are independent, both in terms of their dependencies and in terms of their potential interactions in Ant's external environment.
<parallel threadCount='4'> <ant target='TargetThatConsumesLotsOfCPUTimeAndMemory'> <param name='file' value='one.txt'/> </ant> <ant target='TargetThatConsumesLotsOfCPUTimeAndMemory'> <param name='file' value='two.txt'/> </ant> <ant target='TargetThatConsumesLotsOfCPUTimeAndMemory'> <param name='file' value='three.txt'/> </ant> <!-- repeated about 40 times --> </parallel>
This example represents a typical need for use of the threadCount and threadsPerProcessor attributes. Spinning up all 40 of those tasks could cripple the JVM for memory and the CPU for available time. By limiting the number of concurrent executions you can get the task done in about the same assuming infinite memory time without needing infinite memory. This is also a good candidiate for use of threadCount (and possibly threadsPerProcessor) because each task (in this hypothetical case) is independent and has no dependencies on the other tasks.