質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java EE

Java EE(Java Enterprise Edition)はJavaベースのテクノロジーとその相互運用の仕様をまとめたものです。サーバとクライアントのアーキテクチャを規定し、特定アプリケーションのクラス用に定義されたテクノロジー設定のプロファイルを使用します。

JavaServer Faces

JavaServer Faces(JSF)はJavaをベースとしたコンポーネントベースのwebアプリケーション開発用のフレームワークです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

14597閲覧

javaでログ出力の排他制御を行いたいですのが、どのような手段があるのでしょうか?

rs516

総合スコア12

Java EE

Java EE(Java Enterprise Edition)はJavaベースのテクノロジーとその相互運用の仕様をまとめたものです。サーバとクライアントのアーキテクチャを規定し、特定アプリケーションのクラス用に定義されたテクノロジー設定のプロファイルを使用します。

JavaServer Faces

JavaServer Faces(JSF)はJavaをベースとしたコンポーネントベースのwebアプリケーション開発用のフレームワークです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2016/08/07 07:58

編集2016/08/07 08:57

###前提・実現したいこと
掲題の通りなのですが、javaでログ出力(イベントログ的)の機能を作成したいです。

複数プロセスから同時に書込みがされる事を考え排他制御を行いたいのですが、
素人考えで作成すると排他制御できずにログ内容が混ざって出力されたりすることが不安です。

通常、javaでログ出力機能を作成する場合、どのような方法を取るのでしょうか?
簡単な方法があるのでしょうか?ご教授お願いいたします。

また、排他制御は大きく分けて以下の2パターンになるかと思うのですが、パターン(1)は実現可能でしょうか?
(1)ログ書込み前に排他を取り、既に取られている場合、開放されるまで待機し、解放後処理継続する。
(2)ログ書込み前に排他を取り、既に取られている場合、一定時間待機し、規定回数リトライを行う。一定期間内に排他が開放された場合、ログ出力を行い、開放されなかった場合、ログ出力エラーで例外扱いとする。

質問ばかりで申し訳ありませんが、ご回答の程宜しくお願い致します。

###補足情報(言語/FW/ツール等のバージョンなど)
使用しているのは、java7になります。

###該当のソースコード
package jp.sample;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

/**

  • ログ出力機能のサンプルクラスです。

*/
public class LogWritter {

/** 最大リトライ回数 */ private static final int MAX_RETRY_COUNT = 3; /** インターバル(ミリ秒) */ private static final int RETRY_INTERVAL = 10000; public static void main(String[] args) throws IOException { logWritter("user123", "OK", "2016-0807-1200-00"); } /** * ログ出力の処理です。(引数はとりあえず固定値) * * @param userId ユーザーID * @param result 処理結果 * @param trunDate 処理日時 * @throws IOException */ private static void logWritter(String userId, String result, String trunDate) throws IOException { // ログ出力内容を編集する StringBuilder sb = new StringBuilder(); sb.append(userId); sb.append(result); sb.append(trunDate); sb.append(System.getProperty("line.separator")); // 改行コード File file = new File("C:/work/log/test.log"); FileOutputStream fs = null; int retryCount = 0; try { while (true) { if (retryCount > MAX_RETRY_COUNT) { break; } fs = new FileOutputStream(file, true); FileChannel ch = fs.getChannel(); FileLock lock = null; try { lock = ch.tryLock(); //ロックを取得 // 他プロセスがロック取得してない場合、ログ出力処理を行う。 // ロックがかかっていた場合、1秒待機後にリトライを行う。 if (lock != null) { fs.write(new String(sb).getBytes("UTF-8")); break; } else { Thread.sleep(RETRY_INTERVAL); retryCount++; } } catch (InterruptedException e) { System.out.println("Thread.sleepで例外発生"); e.printStackTrace(); break; } finally { if (lock != null) { System.out.println("排他ロックの開放"); lock.release(); } } } } finally { if (fs != null) System.out.println("ファイルストリームのクローズ"); fs.close(); } }

}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

argius

2016/08/07 09:08

あえて既存のログ出力機能やライブラリーを使わないで実現したいということですか?
rs516

2016/08/07 09:20

読みづらかったりしたら申し訳ありません。 あえて使ってないわけではありません。 loggingクラスの経験が無かったためFileクラスでサンプルを作成しました。 使用するのに制限等あるわけではありません。
rs516

2016/08/07 09:23

経験が浅いため、必要なライブラリや使うべきロジックパターン等が判断できてない。 申し訳ありません。
guest

回答2

0

ベストアンサー

学ぶのが悪いというわけではないですが、
ログ制御のためだけに排他制御を学ぶのはあまりお勧めしません。

ログ出力は専門家(が作ったライブラリー)に任せた方が良いでしょう。

古くはLog4Jというライブラリーが有名です。
最近は、特にWebアプリケーションではLogback + SLF4Jの組み合わせに人気があります。
Java EEだと、CDIを使ったLoggerという手もあります。

javaのロガーが多すぎて訳が解らないので整理してみました - 文系プログラマによるTIPSブログ
http://www.bunkei-programmer.net/entry/2012/10/20/java%E3%81%AE%E3%83%AD%E3%82%AC%E3%83%BC%E3%81%8C%E5%A4%9A%E3%81%99%E3%81%8E%E3%81%A6%E8%A8%B3%E3%81%8C%E8%A7%A3%E3%82%89%E3%81%AA%E3%81%84%E3%81%AE%E3%81%A7%E6%95%B4%E7%90%86%E3%81%97%E3%81%A6

Java EE インジェクト可能なロガーの作り方と注意点 - Qiita
http://qiita.com/potsunen/items/a0dc257fadb8c04e194a

他にもキーワード"Java ロギング"でググればたくさん見つかります。
なるべく新しい記事を探しましょう。古いと細かいところが変わっていたりしますので。

投稿2016/08/07 09:37

argius

総合スコア9388

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rs516

2016/08/07 10:43

ご回答ありがとうございます。 無知で申し訳ないのですが、Log4J、Logback + SLF4J、java util.loggingなどは内部的に排他制御を行うものなのでしょうか? 一般的には、自前でsynchronizedやRunnable等を使って排他制御等は行わないものでしょうか? 今回作成したい要件はWebアプリケーションで複数のユーザーが1ファイルに対して同時更新を行う可能性があるもので、ライブラリが制御するのであれば1番良いのですが、正直自前で実装するには敷居が高く困っています。
argius

2016/08/07 11:14

前述のライブラリーは、広く使われているものですので、 よほど特殊な要件でない限りは、一般的な使い方で問題が出ることはないはずです。 > Log4J、Logback + SLF4J、java util.loggingなどは内部的に排他制御を行うものなのでしょうか? 少なくともsynchronizedは使われています。 詳しくは調べていませんが、前述のライブラリーは非同期の書き込みを行うような設定も可能だと思います。 > 一般的には、自前でsynchronizedやRunnable等を使って排他制御等は行わないものでしょうか? 自作するのであれば、自前でするのはそれほど珍しいことではありません。 > 今回作成したい要件はWebアプリケーションで複数のユーザーが1ファイルに対して同時更新を行う可能性があるもので、ライブラリが制御するのであれば1番良いのですが、正直自前で実装するには敷居が高く困っています。 複数のユーザーが1ファイルに対して同時更新を行うというのは、Webアプリケーションでは当然クリアーされるべき要件ですので、問題ないでしょう。 ただ、複数スレッドでなく、複数プロセスで同じファイルに書きこむ場合は注意が必要かもしれませんので、その辺は調べてみて下さい。 いずれにしても、既存のライブラリーを使うことで (多くの人に使い倒された有名なライブラリーならなおのこと) 自作した場合に発生すると想定される、様々な問題を回避できます。 これはロギングだけの話ではなく、ライブラリーを使う意味そのものでもあります。
rs516

2016/08/07 12:33

丁寧にひとつずつご回答頂き有難うございます。 Logback + SLF4J、もしくは、java util.loggingの方法でアプローチしてみたいと思います。
退会済みユーザー

退会済みユーザー

2016/08/08 01:59

一般的なOSSのログライブラリは、マルチプロセス(マルチスレッドではない)からのログ出力はサポートされていないはずです。 ファイルのロック機構を使う必要があり、java.nio.channels.FileLockを使用するのは良いアプローチだと思います。
guest

0

まず、どれくらいの頻度でイベント? が発生するか
ってのを考えましょう。実はそうたいした頻度じゃない
って話ならば、難しく考える必要はないですよね。

つぎに、複数プロセスとはどういった素性の処理単位か?
例えば、システムにまたがったものだとすると、
専用のデーモンを立ち上げた方がいいでしょうし、
同システム内の複数プロセスという意味なら、
その中で調停すればいい、みたいな。

さらに、もし排他制御の結果ログ出力できなかった場合
どのように対処するかorスルーするか?
必ず出力したいならば、キューイングなどの実装を
必要とするでしょうし、スルーするならば出力依頼は
投げっぱなしてokということになるのかな。

以上のことをふまえて、そういう共通関数的なものにするか
または、専用のインスタンスを用意して実現するか。
そのへんはシステムによってどういった選択がベスト
になるかは評価が分かれるところでしょう。

というところで、具体的な施策は専門家にお任せします。(^_^;

投稿2016/08/07 08:46

takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rs516

2016/08/07 09:14

ご回答ありがとうございます。 複数プロセスは、同シでステム内の複数プロセス(同一アプリケーション・サーバー内)という意味で使いました。 理想だけでいうと必ず出力したいのですが、対象となるログの出力頻度がそう多くないことと、ログ出力に失敗した場合は、画面にログ出力失敗のメッセージを出力すればよいという事からひとまずは簡単な排他制御の仕組みが取れてれば良いのかと考えています。 調べれば調べるほどやり方が幾つかある様で、一般的な(正しい)手法が分からなくなり質問した次第です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問