Inline :: Java与Parallel :: ForkManager冲突

时间:2011-10-13 14:58:54

标签: perl parallel-processing inline

我在同时调用Parallel::ForkManagerInline::Java时遇到问题。具体来说,如果我使用Inline::Java选项(我必须)调用JNI => 1,则fork进程不会返回到父进程。以下是代码:

use Parallel::ForkManager;

##### Calling Inline::Java #####
use Inline Java => <<END, JNI => 1;

END
###### End of Inline::Java #####

my $pm = Parallel::ForkManager->new(2);
for my $i (0..1) {
    $pm->start and next;
    print "Inside process $i\n";
    $pm->finish;
}
$pm->wait_all_children;
print "Back to Parent.\n";

如果我运行此程序,它将进入子进程,但永远不会返回到父进程。如果我删除注释之间的3行,它运行正常。如果我将JNI => 1更改为JNI => 0(不是我允许为了我的目的更改该参数),则会显示Lost connection with Java virtual machine at /usr/lib64/perl5/site_perl/5.8.8/x86_64-linux-thread-multi/Inline/Java.pm line 975的错误消息。

有没有人知道如何解决冲突?我还必须在并行进程之前调用Inline :: Java,因此在并行完成后使用require不是一个选项。 THX!

2 个答案:

答案 0 :(得分:2)

每个孩子都在同一个插座上讲话,导致虚拟机接收乱码。

您需要延迟建立与VM的连接,以便在子节点中完成,而不是在父节点上完成。

您可以将所有与Inline :: Java相关的内容移动到另一个模块中,然后在require Child;之后使用use Child;(不是start)。

如果您需要在启动子项之前使用Inline :: Java,请在其他过程中执行此操作。

答案 1 :(得分:2)

使用Inline::Java分叉将是一个问题。您的perl脚本需要维护与JVM的TCP连接。分叉新进程时,用于与JVM通信的相同文件描述符将传递给子进程,因此父进程和所有子进程都使用相同的套接字。那不行。您需要重新设计您的应用程序。

一种可能性(你已经打折)是延迟启动JVM直到fork之后,在每个子进程中启动一个新的JVM。

另一种方法是忘记从Perl分叉并利用Java的优秀线程模型来进行并行化。设计Java代码以在新线程中执行其任务,并从Perl启动新线程:

my $java = ... entry point to JVM ...

for my $n (1 .. $num_threads) {
    $java->startNewThread(@inputs)
}
$java->waitForThreadsToFinish();
$result = $java->getResults();

Perl也有自己的线程模型(请参阅threadsthreads::shared)。我怀疑Perl的线程是否可以解决这个问题,但它仍然值得一试。


更新:Inline::Java文档中提到的另一种可能性是使用共享JVM。使用选项Inline::Java调用SHARED_JVM => 1,当新的子进程启动时,从子进程调用Inline::Java::reconnect_JVM()以建立新连接。这种方法的缺点是

  1. 它在程序结束后保持JVM处于活动状态,因此您必须记住杀死JVM
  2. 它与选项JNI => 1不兼容,后者可能是OP的交易破解者。