- PR -

一つのファイルに対する複数ストリームについて

1
投稿者投稿内容
未記入
ベテラン
会議室デビュー日: 2005/02/24
投稿数: 55
投稿日時: 2005-04-08 17:08
一つのファイルに対して複数ストリームを開き
それぞれがファイルにログを書き込むというプラグラムを作成しました。

一応今のところ正常に動作しているのですが、
同時に書き込みが行われた場合もエラーが発生しないかどうか心配です。

もし同時書き込みが行われた場合にエラーは発生したりしないのでしょうか?
下にプログラムの該当メソッドをを記します。

public class Sample {
public static void log(String str, Throwable e) {
FileWriter fWriter = new FileWriter("c:\\tmp\\log.log");
PrintWriter pWriter = new PrintWriter(pWriter);

fWriter.write(str);
fWriter.flush();
e.printStackTrace(pWriter);
pWriter.flush();
}
}

環境 Solaris 5.7 JDK1.2.2 Tomcat3.1




Edosson
ぬし
会議室デビュー日: 2004/04/30
投稿数: 675
投稿日時: 2005-04-08 17:34
引用:

もし同時書き込みが行われた場合にエラーは発生したりしないのでしょうか?


そういう期待をするよりも、同時書き込みを制限するコードを記述したほうが確実ですよね。。
ログ出力ロジックなら、
・SampleクラスをSingletonにする。
・logメソッドはsynchronizedにする。
といったところでしょうか。
コード:

public class Sample {
private static Sample instance = null;

//他のクラスから、newによるインスタンス化の禁止
private Sample() {
super();
}

//Simpleのインスタンスを生成できるのは、このメソッドだけ
public static Sample getInstance() {
if (insatance == null) {
instance = new Sample();
}
return instance;
}

public synchronized void log(String str, Throwable e) {
FileWriter fWriter = new FileWriter("c:\tmp\log.log");
PrintWriter pWriter = new PrintWriter(fWriter);

fWriter.write(str);
fWriter.flush();
e.printStackTrace(pWriter);
pWriter.flush();
pWriter.close();
}
}

//使い方
class Owner {
public static void main(String[] args) {
Sample sample = Sample.getInstance();
.....
sample.log( str, e );
}
}


ちょこっといじくらせていただきました。

[ メッセージ編集済み 編集者: Edosson 編集日時 2005-04-08 17:59 ]
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2005-04-10 19:15
WindowsXPでCPU2個(HT)でスレッド10個でやってみましたが正常に動作しました。
ただしFileWriterのJavaDocには

* Some platforms, in particular, allow a file to be
* opened for writing by only one <tt>FileWriter</tt> (or other file-writing
* object) at a time. In such situations the constructors in this class
* will fail if the file involved is already open.

とあるのでOSやVM依存となると思います。おそらくOSかVMで直列にしてくれるのでしょうがおそらく書き込みが成功するまで待ち状態になることを考えるとJava側で書き込み処理をキューイングしてやらないとこのロギングが深刻なパフォーマンスの問題を発生させる可能性も考えられます。自力でそうしたコードを記述するのは大変なのでLog4jやJavaのloggingパッケージを利用することをお勧めします。
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2005-04-10 20:47
同時書き込みが行われた場合にエラーになる可能性はないか?
ということに関してなら、心配は無用です。
ただし、プログラムが意図通りに動いてくれるかどうかは別問題です。

例えば、
コード:
   hogeOut.print("name=");
   hogeOut.println(name);


のようなコードが複数スレッドから呼び出された場合に
name=name=barfoo
などと出力が混じってしまうのを防止したいのであれば、
Javaのレベルでも同期化の仕掛けを施しておく必要があります。

未記入
ベテラン
会議室デビュー日: 2005/02/24
投稿数: 55
投稿日時: 2005-04-11 11:17
結局Edossonさんの案を参考にして
Singletonとsyncronizedを使用することにしました。

ロギングフレームワークを使用することは、
アプリがエラーさえ起こらなければいいので
今回は見送ります。

みなさんどうもありがとうございました。
1

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