我在同时调用Parallel::ForkManager
和Inline::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!
答案 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也有自己的线程模型(请参阅threads
和threads::shared
)。我怀疑Perl的线程是否可以解决这个问题,但它仍然值得一试。
更新:Inline::Java
文档中提到的另一种可能性是使用共享JVM。使用选项Inline::Java
调用SHARED_JVM => 1
,当新的子进程启动时,从子进程调用Inline::Java::reconnect_JVM()
以建立新连接。这种方法的缺点是
JNI => 1
不兼容,后者可能是OP的交易破解者。