Multithreading ApacheAnt上线程安全的并行数学操作
我正在与Ant并行运行几个子任务 这是build.xml的简化内容:Multithreading ApacheAnt上线程安全的并行数学操作,multithreading,ant,parallel-processing,ant-contrib,Multithreading,Ant,Parallel Processing,Ant Contrib,我正在与Ant并行运行几个子任务 这是build.xml的简化内容: <target name="parallelOperations"> <var name="port.number" value="9006"/> <for list="a,b,c,d,e" param="letter" parallel="true"> <sequential> <echo>Letter @{l
<target name="parallelOperations">
<var name="port.number" value="9006"/>
<for list="a,b,c,d,e" param="letter" parallel="true">
<sequential>
<echo>Letter @{letter}</echo>
<math result="port.number" operand1="${port.number}" operation="+" operand2="1" datatype="int"/>
<echo>${port.number}</echo>
</sequential>
</for>
</target>
这里发生的是对于列表中的每个元素,它打印元素的内容和加号操作的结果。这里的问题是数学操作不是线程保存,这意味着每个操作同时访问变量$port.number,添加一个值,然后分配该值
有没有办法用Ant实现线程安全?我试图做的是,对于并行运行的每个子任务,获得一个唯一的端口号。如果有其他方法,它也可能是一个很好的解决方案。这来自:
的主要用例是同时运行外部程序,如应用程序服务器和JUnit或TestNG测试套件。任何试图并行运行大型Ant任务序列的人,比如同时运行javadoc和javac,都隐含地承担了识别和修复它们运行的任务中所有并发错误的任务
因此,同步操作取决于用户。可能有两种解决方案:
使用任务使每个线程等待某个条件为真,例如设置了属性
实现您自己的同步任务。描述一种编写任务的方法,该任务可以接受id并对其进行锁定
第一个解决方案更简单,通常用于这种同步。我将回答我自己的问题,发布具体的解决方案,以防有人需要它 这是可行的解决方案:
<target name="ParallelOperations">
<var name="port.number" value="9006"/>
<for list="a,b,c,d" param="letter" parallel="true">
<sequential>
<echo>Letter @{letter}</echo>
<!-- Synchronize the port number -->
<synchronized id="port.number.lock">
<echo>@{letter} new port ${port.number}</echo>
<var name="@{letter}.port.number" value="${port.number}" />
<math result="port.number" operand1="${port.number}" operation="+" operand2="1" datatype="int"/>
</synchronized>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
</sequential>
</for>
从@manouti的答案中,我从Stefan Fanke那里选择了synchronized命令,并使用每个字母创建一个特定变量来存储端口号
正如您所看到的,每个字母都分配了自己唯一的端口号。waitfor对我来说是不够的。Stefan Frank关于问题2的同步的实施是正确的。谢谢你!
<target name="ParallelOperations">
<var name="port.number" value="9006"/>
<for list="a,b,c,d" param="letter" parallel="true">
<sequential>
<echo>Letter @{letter}</echo>
<!-- Synchronize the port number -->
<synchronized id="port.number.lock">
<echo>@{letter} new port ${port.number}</echo>
<var name="@{letter}.port.number" value="${port.number}" />
<math result="port.number" operand1="${port.number}" operation="+" operand2="1" datatype="int"/>
</synchronized>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
<echo>@{letter} ${@{letter}.port.number}</echo>
</sequential>
</for>
ParallelOperations:
[echo] Letter d
[echo] Letter a
[echo] Letter c
[echo] Letter b
[echo] c new port 9006
[echo] c 9006
[echo] b new port 9007
[echo] c 9006
[echo] c 9006
[echo] b 9007
[echo] c 9006
[echo] a new port 9008
[echo] b 9007
[echo] c 9006
[echo] b 9007
[echo] c 9006
[echo] a 9008
[echo] d new port 9009
[echo] c 9006
[echo] b 9007
[echo] a 9008
[echo] d 9009
[echo] b 9007
[echo] a 9008
[echo] d 9009
[echo] c 9006
[echo] a 9008
[echo] b 9007
[echo] d 9009
[echo] a 9008
[echo] b 9007
[echo] d 9009
[echo] a 9008
[echo] b 9007
[echo] d 9009
[echo] a 9008
[echo] d 9009
[echo] a 9008
[echo] d 9009
[echo] d 9009