理由が判らん!
stratup.batで起動とサービスで起動で動作が違う?
http://d.hatena.ne.jp/S_a_k_U/20070617/p2
が解決できた(っぽい)けど、全然納得できん!
【処理概要】
トランザクション処理の中にID発番処理がある。
ID発番は発番テーブルを利用し、発番済みの最大番号を持っており、発番する度に+1する。
素直に登録処理を作り、ID発番の処理を同じトランザクションスコープに入れると、ID発番の処理がトランザクションの処理時間待たされてしまう。
あるリクエストで登録処理を行っている最中に、次のリクエストが登録処理を行う場合、先発の処理が終了するまで、後発のリクエストはID発番処理(a1)で待ちが発生する。
(登録処理が事実上シングルスレッド?処理になる)
登録処理開始(トランザクション開始) ↓ ID発番処理(a1) ← ここで後発の登録処理が待たされる ↓ 登録処理(a2) ↓ 登録処理終了(トランザクション終了)
【改善策】
ということで、ID発番処理(a1)を別スレッドで行うように下記のようにした。
ID発番処理(b1.1)では、登録処理とは別のトランザクションでID発番処理を行い、発番後のIDを登録処理のIDにセットする。
ID発番の監視(b2)では、登録処理のIDの値をwhile文で監視し、ID発番処理(b1.1)がIDをセットした(発番処理が終了した)時点で、そのIDを持って登録処理を行う。
登録処理開始(トランザクション開始) ↓ ID生成処理(b1) −−−→(別スレッド)→ ID発番処理(b1.1)(トランザクションあり) ↓ ID発番の監視(b2) (while文ループでIDの値を監視) ↓ 登録処理(b3) ↓ 登録処理終了(トランザクション終了)
ID発番処理(b1.1)では、SELECT FOR UPDATE文での排他制御を行っているため、デッドロックが発生しているのか?と疑ってみたり。
でも、発番テーブルを確認すると、最大番号が+1され、正常に処理が終了していた。
止まってる状態でタスクマネージャを見てみると、CPUが100%(実際はデュアルプロセッサのため50%)で一定になっていたため、ID発番の監視(b2)のwhile文のループで、無限ループしたままの状態と予想してみる。
ID発番の監視(b2)の処理は下記のような感じ。
public int generate() { // IDの初期値 setId(0); // ID発番処理(b1.1)[別スレッドで処理] counter.start(); // ID発番の監視(b2) while (true) { // counterがIDをセットしたか? if (getId() > 0) { break; } } return getId(); }
IDがどうなっとんか確認するため、「counterがIDをセットしたか?」をチェックするif文の後ろに、System.outでgetId()を出力してみたらすんなり処理が走り出した…
なんでじゃぁぁぁぁぁ〜
ということで、Thread.sleep(1);を入れたら解決した。
public int genarate() { // IDの初期値 setId(0); // ID発番処理(b1.1)[別スレッドで処理] counter.start() // ID発番の監視(b2) while (true) { try { Thread.sleep(1); // counterがIDをセットしたか? if (getId() > 0) { break; } } catch (Exception e) { // ログ書いてから抜ける break; } } return getId(); }
Windows版のTomcatで、statup.batで起動した時と、サービスで起動した時で何が違うんじゃ???
無限ループで監視するってのはsleep入れるのがセオリーなんじゃろか???
そもそも、1ミリ秒って待ちは適切なんじゃろか???
何はともあれ、とりあえず当面これで様子を見てみよう。
ということで、JavaでThreadとかRunableとか使ってみたことかるかどうかとかも、プログラミング以外も含めたスキルを計るイイ目安になるかもしれん。