diff --git a/docs/manual/CoreTasks/parallel.html b/docs/manual/CoreTasks/parallel.html index aec859f56..738132565 100644 --- a/docs/manual/CoreTasks/parallel.html +++ b/docs/manual/CoreTasks/parallel.html @@ -11,6 +11,31 @@
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 | +Maximum number of milliseconds to wait for before checking +when waiting for available threads. | +No, default is 1000 | +
Parallel tasks have a number of uses in an Ant build file including:
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 insure +that the build does not deadlock. This can be caused by tasks such as waitFor +takeing 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 "embarasingly parallel" tasks.
+<parallel> @@ -75,6 +120,31 @@ 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.
+
Copyright © 2001-2002 Apache Software Foundation. All rights Reserved.
diff --git a/src/etc/testcases/taskdefs/parallel.xml b/src/etc/testcases/taskdefs/parallel.xml index 2420de7fe..4f2e050f2 100644 --- a/src/etc/testcases/taskdefs/parallel.xml +++ b/src/etc/testcases/taskdefs/parallel.xml @@ -22,103 +22,97 @@- diff --git a/src/testcases/org/apache/tools/ant/taskdefs/ParallelTest.java b/src/testcases/org/apache/tools/ant/taskdefs/ParallelTest.java index 203f00cc8..aed328b36 100644 --- a/src/testcases/org/apache/tools/ant/taskdefs/ParallelTest.java +++ b/src/testcases/org/apache/tools/ant/taskdefs/ParallelTest.java @@ -53,10 +53,13 @@ */ package org.apache.tools.ant.taskdefs; import java.io.PrintStream; +import junit.framework.AssertionFailedError; +import org.apache.tools.ant.BuildException; import org.apache.tools.ant.BuildFileTest; import org.apache.tools.ant.DemuxOutputStream; import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; /** * Test of the parallel TaskContainer @@ -104,17 +107,59 @@ public class ParallelTest extends BuildFileTest { } /** tests basic operation of the parallel task */ - public void testTreadCount() { + public void testThreadCount() { // should get no output at all Project project = getProject(); project.setUserProperty("test.direct", DIRECT_MESSAGE); project.setUserProperty("test.delayed", DELAYED_MESSAGE); expectOutputAndError("testThreadCount", "", ""); String log = getLog(); - assertEquals("parallel tasks did't block on threads properly", log, - "+1-1+2-2+3-3+1+2-1+3-2-3+1+2+3-1-2-3+1+2+3-1-2-3"); - + int pos = 0; + while (pos > -1) { + pos = countThreads(log, pos); + } + } + + /** + * the test result string should match the regex + *- + |1/ ++ - - - + + + - - - + + + - - - + + + |2/ - +- - - + + + - - - - + + + - - - - + + + |3/ - +- - - + + + - - - - + + + - - - - + + + |4/ - -- - - + + + - - - - + + + - - - - + + + - - + |4/ ++ - - - + + + - - - + + + - - - + + + | ^(\|\d+\/(+-)*)+\|$
for someting like + *|3/++--+-|5/+++++-----|
+ * + *@returns -1 no more tests + * # start pos of next test + *@throws AssertionFailedException when a constraint is invalid + */ + static int countThreads(String s, int start) { + int firstPipe = s.indexOf('|', start); + int beginSlash = s.indexOf('/', firstPipe); + int lastPipe = s.indexOf('|', beginSlash); + if ((firstPipe == -1) || (beginSlash == -1) || (lastPipe == -1)) { + return -1; + } + + int max = Integer.parseInt(s.substring(firstPipe + 1, beginSlash)); + int current = 0; + int pos = beginSlash + 1; + while (pos < lastPipe) { + switch (s.charAt(pos++)) { + case '+': + current++; + break; + case '-': + current--; + break; + default: + throw new AssertionFailedError("Only expect '+-' in result count, found " + + s.charAt(--pos) + " at position " + pos); + } + if (current > max) { + throw new AssertionFailedError("Number of executing threads exceeded number allowed: " + + current + " > " + max); + } + } + return lastPipe; } + /** tests the failure of a task within a parallel construction */ public void testFail() { @@ -142,5 +187,6 @@ public class ParallelTest extends BuildFileTest { System.setErr(err); } } + }