- PR -

排他処理について

1
投稿者投稿内容
Boy
会議室デビュー日: 2007/01/20
投稿数: 7
投稿日時: 2007-03-30 20:58
いつもお世話になっています。
早速ですが、質問させていただきます。

処理A、処理B、処理Cがあったときに
処理Aの終了を確認→処理B開始、処理Bの終了を確認→処理C
と進めて行きたいのですが、うまくいきません。

各処理は
処理A・・・計算で使う.keyファイルを作成及び更新
処理B・・・外部ソフトによる計算。.xyz、.keyファイルを使い、.logファイルを作成
処理C・・・計算結果から必要部抜き出し。.logファイルを使い、.txtファイルを作成
となっています。
これを繰り返すのですが、処理処理Bが終わっていないのに処理Cが始まり、さらにAへと続いてしまいます。

排他処理や、同期化のwebページなども参考にしましたが、
外部計算ソフトの実行終了を待つにはどうしたらいいのでしょうか?
webによれば、処理AとBは.keyファイル、処理BとCは.logファイルで制御出来そうなのですが・・・
処理Bにおいてそれぞれのファイルはコマンドライン上で入力されるだけなので、
synchronizedでは上手くいかないような気もします。
sleepで十分大きな待ち時間を設定する事も考えましたが、それではあまりに非効率的なので・・・

以下に簡単に、問題部を書きます。


do{ //ループ開始

//処理A、パラメタ更新(.keyファイルの更新)
a[i] -= 0.005;
try{
File file = new File("xxx.key");
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
pw.println(" ");
pw.println("# Crystal Lattice And Periodic Boundary");
pw.println("A-AXIS "+a[i]);
pw.close();
}catch(IOException e){
System.out.println(e);
}


//処理B(外部ソフトによる計算)
try {
     Process process = Runtime.getRuntime().exec("cmd.exe /c minimize.exe \"xxx.xyz_\"" + j + " 0.01 -k \"xxx.key\" > \"xxx.log\"" );
} catch (Exception e) {
e.printStackTrace();
}


//処理C(計算結果から必要な値を抜き出す)
try {
Process process = Runtime.getRuntime().exec("cmd.exe /c grep Function xxx.log > test.txt");
} catch (Exception e) {
e.printStackTrace();
}
try {
int k = 0;
FileReader fr=new FileReader("test.txt");
StreamTokenizer st=new StreamTokenizer(fr);
while(st.nextToken()!=StreamTokenizer.TT_EOF) {
temp[k]=st.nval;
k++;
}
fr.close();
} catch(Exception e) {
System.out.println(e);
}


環境はj2SDK 1.4.2_13 です。

まだまだ排他処理についての勉強が浅いので自分でも色々と試してみますが、
何かこの問題について妙案がありましたら、ぜひご教授いただけ るとありがたいです。

よろしくお願いします。

[ メッセージ編集済み 編集者: Boy 編集日時 2007-03-30 21:05 ]

[ メッセージ編集済み 編集者: Boy 編集日時 2007-03-30 21:14 ]
小僧
ぬし
会議室デビュー日: 2002/08/14
投稿数: 526
投稿日時: 2007-03-30 21:03
ProcessクラスのwaitForメソッドを試してみてはいかが。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-03-31 17:29
排他処理ということはこれら3種のメソッドが別スレッドで動いているということですか?
Boy
会議室デビュー日: 2007/01/20
投稿数: 7
投稿日時: 2007-03-31 23:01
小僧さん>
ありがとう御座います。試してみます。


nagiseさん>
すいません、排他処理の意味を取り違えたようです。
今の所、メイン無いにこの一連の流れが入っている形です。
なので、別スレッドで動いてる訳ではありません。
なにぶん知識が乏しいので誤解を招く表現を使ってしまいすいません。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2007-04-01 13:42
別プロセスである処理Bが終了しているかどうかをどうすれば判定できるか、ということですよね?
で、 .log ファイルは処理が終了していなくても処理の過程で作成されてしまうことが判定を難しくしているということでしょうか?

では終了判定専用のファイルを作ってはいかがでしょう。
一番簡単そうなのは、処理Bで Process#waitFor でminimize.exe の終了をまって判定用のファイルを作ることかな。
処理B で、new File("xxx.done").createNewFile();
処理C で、
while(!new File("xxx.done").exists()){
Thread.sleep(1000);
}
とファイルができるまで待つことです。


または処理Bが処理Cを起動するようにするとか。たぶん現在の設計上それができないからこのスレッドがあるのだと思いますが。
Boy
会議室デビュー日: 2007/01/20
投稿数: 7
投稿日時: 2007-04-07 22:38
インギさん>
大変遅くなりました。すいません。
ご指摘の通りです。処理Bが処理Cの起動を出来る設計ではありません。
また、処理を外部に出した瞬間プログラム本体が先へ進んでしまうための困難です。
アドバイス大変参考になりました。
.batファイルと組み合わせて解決出来ました。


・処理B実行
・bbb.doingファイル削除
というb.batファイルと、

・処理C実行
・ccc.doingファイル削除
というc.batファイルを作成して、問題部を



//処理A(省略)

//処理B
File bfile = new File("bbb.doing");
bfile.createNewFile();

try {
Process process = Runtime.getRuntime().exec("b.bat");
} catch (Exception e) {
e.printStackTrace();
}

while(bfile.exists()){
Thread.sleep(1000);
}

//処理C
File cfile = new File("ccc.doing");
cfile.createNewFile();

try {
Process process = Runtime.getRuntime().exec("c.bat");
} catch (Exception e) {
e.printStackTrace();
}

while(cfile.exists()){
Thread.sleep(1000);
}


どうやら.batファイルでの制御ですと、上の処理が終わらないと下の処理に移らないらしいです。
また、皆様に教えていただいたProcess#waitForでも解決できそうなので、ぜひこの機会にもっと勉強しようと思います。

今回は有り難う御座いました。
また何かありましたらよろしくお願い致します。
1

スキルアップ/キャリアアップ(JOB@IT)