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

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

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

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

バッチファイル

バッチファイル(Batch File)は、Windowsのコマンドラインインタープリターによって複数のコマンドを実行させる事が出来るスクリプトファイルです。

ファイルI/O

ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。

Q&A

解決済

2回答

6808閲覧

Javaアプリケーションの二重起動を確実に処理したい

taa-sap_032

総合スコア5

Java

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

バッチファイル

バッチファイル(Batch File)は、Windowsのコマンドラインインタープリターによって複数のコマンドを実行させる事が出来るスクリプトファイルです。

ファイルI/O

ファイルI/Oは、コンピューターにおけるファイルの入出力です。これは生成/削除やファイルを読み込んだり、出力をファイルに書き込むようなディレクトリやファイルの運用を含みます。

0グッド

3クリップ

投稿2021/04/20 08:21

###やりたいこと
Javaのバッチ処理アプリケーションを作成する。
アプリケーションにはロックファイルのロック状態を参照して、ロック中ならそこで処理終了することによりアプリケーションの二重起動を防ぐ機能を持たせる。

発生している問題・エラーメッセージ

Windows環境で、Jar形式にしたJavaアプリケーションの動作確認を行っているが、場合により二重起動が防止できない。

java

1 2public class XXXMain { 3 4 public static void main(String[] args) { 5 boolean ret = false; 6... 7 //起動チェック 8 try { 9... 10 String lockFileName = logPath + "/XXX.lock"; 11 final FileOutputStream fos = new FileOutputStream(new File(lockFileName)); 12 final FileChannel fc = fos.getChannel(); 13 final FileLock lock = fc.tryLock(); 14 if (lock == null) { 15 //既に起動されているので終了する 16 logger.info("既に起動されているので終了する"); 17 System.exit(1); 18 } 19 20 //ロック開放処理を登録 21 Runtime.getRuntime().addShutdownHook( 22 new Thread() { 23 public void run() { 24 try { 25 if (lock != null && lock.isValid()) { 26 lock.release(); 27 } 28 fc.close(); 29 fos.close(); 30 } catch (IOException e) { 31 e.printStackTrace(); 32 } 33 } 34 } 35 ); 36 37 XXXLogic class1 = new XXXLogic(); 38 39 class1.setApplicationPath(mainClassPath); // アプリケーションのパス設定 40 ret = class1.dologic(logger, props); // メール編集->DB登録処理メイン 41 42... 43 System.exit(0); 44 } catch (Exception e) { 45 e.printStackTrace(); 46 System.exit(2); 47 } 48 49 } 50} 51

試したこと

・コマンドプロンプトを2つ開いて、コマンドプロンプト(1)とコマンドプロンプト(2)でほぼ同時にアプリケーションを開始する
→両方のアプリケーションが二重起動チェックの箇所を越えてメイン処理が実行されてしまう。
(後に実行した方のアプリケーションがファイルロック箇所で処理終了してほしい)
・Eclipseをデバッグ実行して、ファイルロックをかけた状態でデバッガで停止させた状態
→コマンドプロンプトからJar形式のアプリケーションを実行する
→コマンドプロンプトから実行したアプリケーションはファイルロック箇所で処理終了する。

補足情報(FW/ツールのバージョンなど)

Java1.8
Eclipse環境で実行、Jar形式をコマンドプロンプトから実行

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

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

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

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

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

dodox86

2021/04/21 05:09

抜粋されたコードなので確認です。この部分ですが、 > String lockFileName = logPath + "/XXX.lock"; logPathは常にその2つのプロセスで同じPATHを指していますか。つまり、正しく、同じファイルのPATHを指していますか。
taa-sap_032

2021/04/21 05:20

logpathの取得部分は省略してしまったのですが、2つのプロセスで同じプロパティファイルからパス項目を取得してファイルパスを生成しており、同じファイルのパスになっています。
szk.

2021/04/21 13:49

「ロックファイル」を使うことは必須なんですか?
taa-sap_032

2021/04/21 17:19

ロックファイルを使う方法でしか対応出来ない、というわけではないようなので他の方法も考えてみます。 本番環境はlinuxなのでプロセスidまたはプロセス名で同じものを検知する?方法も検討しています。
guest

回答2

0

ベストアンサー

ちょっと試してみましたけど、こちらの環境では問題は発生しませんでした。
jdk-15.0.2 (Windows10)

なんでしょうね…

コマンドプロンプトを2つ開いて、コマンドプロンプト(1)とコマンドプロンプト(2)でほぼ同時にアプリケーションを開始する

ちなみに、ほぼ同時ではなければ(少し間をおくなど)問題は発生しませんでしょうか?

投稿2021/04/26 12:09

pg-tips

総合スコア57

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

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

taa-sap_032

2021/04/27 07:08

>ほぼ同時ではなければ(少し間をおくなど)問題は発生しませんでしょうか? ロック取得の直後に30秒ほど時間を遅延させる処理(TimeUnitのsleep())を入れた状態でアプリケーションを2か所から実行したところ、二重起動検知→終了と処理本体の実行に分かれたので、複数個所からの実行も間隔が狭すぎなければ二重起動検知は有効なのかと思います。 (実際に動かしたときにどの程度処理時間がかかるのかまだわからないのですが...)
dodox86

2021/04/27 07:33

横からすみません。 > 複数個所からの実行も間隔が狭すぎなければ二重起動検知は有効なのかと思います。 間隔が狭かろうがほぼ同時であろうが、複数の並列(なかんじ)の処理を抑止するためのロックなので、それではダメなのではないかと思います。本質問が投稿された当初、私もコードを簡単にした上でJava8、 11で試しましたが、問題は再現しませんでした。(<なので回答はしませんでした) 疑う訳ではないのですが、プロパティファイルからPATHを取得しているとのことですが、実際に起動するときに違う値になってしまっているということはありませんでしょうか。
pg-tips

2021/04/27 14:08

私もdodox86さんと同じで、タイミングの問題ではなく、なにか別の問題なのかなと思って質問させていただきました。(同時じゃなくても問題は再現するのではないかなと思って) FileLock自体はAPI仕様に > ファイル・ロックはJava仮想マシン全体のために保持されます。 > https://docs.oracle.com/javase/jp/8/docs/api/java/nio/channels/FileLock.html とあるので二重起動のチェックに使うのは問題ないと思います。 手がかりを得るには… - 実は違うファイルをロックしてしまっていないか - 変にプロセスが残っちゃっていてファイルロックしたままになっていないか(タスクマネージャーでJavaプロセスを確認してみるとか) - 実は例外が発生していてe.printStackTrace()でなにか表示されていないか - addShutdownHookは期待したとおりのタイミングで動いているか(想定より早くlock.releaseされてないか) あたりでしょうか。 それでもダメであれば、余計なコードを削除した二重起動チェックだけのシンプルなサンプルを作って、問題が再現するかどうか確認してみるのもよいかもです。
guest

0

FileChannelつかって、FileLockつかって。なんかかっこういいですが、StandardOpenOption.CREATE_NEWで十分目的は果たせるのではないかと。
「確実に」の保証があるかどうかはわかりませんけど。

java

1import java.nio.file.*; 2 3public class HogeLock{ 4 private static final Path LOCK_FILE = Paths.get("/tmp/.lock"); 5 6 public static void main(final String[] args) throws Exception { 7 Files.newOutputStream(LOCK_FILE, StandardOpenOption.CREATE_NEW); 8 Thread.sleep(1000); 9 Files.delete(LOCK_FILE); 10 } 11}

投稿2021/04/23 00:56

shiketa

総合スコア4041

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問