2011-10-13 29 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