2011-10-13 28 views
3

我在同时调用Parallel::ForkManagerInline::Java时遇到问题。具体来说,如果我用JNI => 1选项(我必须)调用Inline::Java,那么fork过程不会返回到父项。下面是代码:Inline :: Java与Parallel :: ForkManager冲突

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不是一个选项。谢谢!

回答

2

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

您需要延迟与VM建立连接,以便它在孩子而不是父母中完成。

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

如果您在启动孩子之前需要使用Inline :: Java,请在不同的过程中执行此操作。

+0

欣赏你的分析。但是,不幸的是,您的解决方案不适合我实现,正如我在最初的问题结尾处指出的那样,Inline :: Java过程必须在* fork之前执行。顺便说一句,Inline :: Java已经在一个单独的模块中。为了说明的目的,我在这里合并了所有脚本。 – Zhang18

+0

@ Zhang18,再次阅读。我的解决方案并不妨碍您在P :: FM循环之前使用Inline :: Java。你只需要在一个单独的过程中完成。 – ikegami

+0

我明白了 - 你是对的。我没有进入每个子进程来调用JVM,而是设法只进入一个子进程,调用JVM,将结果返回给父进程,然后分叉到许多子进程中。所以关键是永远不要在父项中运行JVM。多谢! – Zhang18

2

Inline::Java使用叉将会成为一个问题。您的perl脚本需要与JVM保持TCP连接。当您分叉一个新进程时,与JVM通信的相同文件描述符被传递给子进程,以便父进程和所有子进程使用相同的套接字。这是行不通的。你需要重新设计你的应用程序。

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

另一种方法是忘记从Perl分叉并利用Java的高级线程模型进行并行化。从Perl的设计您的Java代码在新的线程执行其任务,并开始新主题:

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。使用SHARED_JVM => 1选项调用Inline::Java,并且当新的子进程启动时,请从子项调用Inline::Java::reconnect_JVM()以建立新的连接。这种方法的缺点是

  1. 它使JVM中的活动程序结束后,所以你一定要记得杀JVM
  2. 它与选项JNI => 1,这可能是一个因素在于对OP不兼容。
+0

Perl的线程不会有帮助,因为你仍然有同样的问题试图同时使用同一套接字。 – ikegami

+0

要明确,Java线程方法应该可以工作。我的评论只针对暴徒最后一段的评论。 – ikegami