- PR -

JavaAppletで start後 に run が呼ばれないことがある

1
投稿者投稿内容
rika
会議室デビュー日: 2004/02/23
投稿数: 4
投稿日時: 2004-02-23 10:23
はじめまして。rikaと申します。
JavaAppletで作成しているのですが、startでスレッドを生成し、スレッドスタートを
呼んでいるのですが、その後に来るはずの run が来ないで、Appletが止まってしまうことがあります。原因がわからなく何かご存知の方がいらっしゃいましたら教えていただきたく投稿させていただきました。

環境は、WinXP,Win2000 IE6.0 J2SDK1.4.2 です。

抜粋ですが、以下がソースです。

public class imgdsp extends java.applet.Applet implements Runnable,MouseListener
{
  Thread thr;

  /* 初期化ルーチン */
  public void init() {
    System.out.println( "init 開始");

    // 初期化処理

    System.out.println( "init 終了");
  }

  /* 描画 */
  public void paint( java.awt.Graphics g ){
    System.out.println( "paint呼ばれました" );

    // 描画処理
  }

  public void start(){
    System.out.println( "start呼ばれました" );

    /** スレッドを起動 **/
    if( thr == null ){
      thr = new Thread( this );
      System.out.println( "スレッド生成開始 thr.start()" );
      thr.start();
      System.out.println( "スレッド生成終了 thr.start()" );
    }
  }

  public void stop(){
    System.out.println( "stop呼ばれました" );

    /** スレッドを停止 **/
    if( thr != null ){
      thr.interrupt();
      System.out.println( "スレッド強制終了 thr.interrupt()" );

      try{
        System.out.println( "スレッド同期開始 thr.join()" );
        thr.join();
        System.out.println( "スレッド同期終了 thr.join()" );
      }
      catch(InterruptedException e){
      }

      thr = null;
      System.out.println( "スレッド thr = null" );
    }
  }

  public void run(){
    System.out.println( "run呼ばれました" );
    Thread thisThread = Thread.currentThread();

    while( thr == thisThread ){
      // ループ処理
    }
  }

とまってしまう時のJavaコンソールは、
 init 開始
 init 終了
 スレッド生成開始 thr.start()
 スレッド生成終了 thr.start()
で、終わっています。
この現象は、初めてページを開いたときに発生することもありますし、何回か連続でブラウザの更新ボタンを押していると発生したりします。

どうぞよろしくお願いします。
コブラ
ぬし
会議室デビュー日: 2003/07/18
投稿数: 1038
お住まい・勤務地: 神奈川
投稿日時: 2004-02-23 11:20
import java.applet.*;
import java.applet.Applet;
import java.awt.event.*;

public class rika extends Applet implements Runnable, MouseListener
{
Thread thr;

public void init() {
System.out.println( "init ");
}

public void paint( java.awt.Graphics g ){
System.out.println( "paint" );
}

public void start(){
System.out.println( "start" );

if( thr == null ){
thr = new Thread( this );
System.out.println( " thr.start()" );
thr.start();
}
}

public void stop(){
System.out.println( "stop" );

if( thr != null ){
thr.interrupt();
System.out.println( " thr.interrupt()" );

try{
System.out.println( " thr.join()" );
thr.join();
System.out.println( " thr.join()" );
}
catch(InterruptedException e){
}

thr = null;
System.out.println( " thr = null" );
}
}

public void run(){
System.out.println( "run" );
Thread thisThread = thr.currentThread();

while( thr == thisThread ){
}
}

public void mouseClicked(MouseEvent e){
}

public void mousePressed(MouseEvent e){
}

public void mouseReleased(MouseEvent e){
}

public void mouseEntered(MouseEvent e){
}

public void mouseExited(MouseEvent e){
}
}

いやぁ、、リロードしても15秒ぐらい待ったらちゃんと run() て必ず表示してますけど。。。
J2SE1.4.2_02 環境ですが。

ただ、短気やったんで結果を見る前にブラウザ閉じたとか?(笑)
rika
会議室デビュー日: 2004/02/23
投稿数: 4
投稿日時: 2004-02-23 14:00
コブラ様、検証いただいてありがとうございます。

>いやぁ、、リロードしても15秒ぐらい待ったらちゃんと run() て必ず表示してますけど。。。
>J2SE1.4.2_02 環境ですが。

>ただ、短気やったんで結果を見る前にブラウザ閉じたとか?(笑)

いやいや、そんなに短い間でブラウザを閉じたりはしてないんですが・・・。
止まってしまうときは、3分ぐらい待っても反応無しです。
ブラウザも反応しなくて CTRL + ALT + DEL で強制的に終了させなければ終了もしないんです。完全に固まってるみたいで、Javaコンソールにも応答なしって出てます。

一つ書き忘れてたんですが(すみません)、このソフトはフレーム上からページを開くようになっています。上中下と3分割されたフレームの上側でページ切り替えして中段にそのページが開くようになっています。その1つがアプレットを開くようになっていて、アプレットじゃない普通のページと交互に切り替えていると、よくこの現象がでるような気がします。

あいまいな表現で本当に申し訳ないんですが、どうぞもう少しお力をお貸しください。
よろしくお願いします。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-02-24 16:58
unibon です。こんにちわ。

引用:

rikaさんの書き込み (2004-02-23 14:00) より:
ブラウザも反応しなくて CTRL + ALT + DEL で強制的に終了させなければ終了もしないんです。完全に固まってるみたいで、Javaコンソールにも応答なしって出てます。


「Java Console」に「応答なし」と表示されることがありましたっけ。タスクマネージャーのことではないでしょうか。
雰囲気を拝見すると、Java Applet 側の問題というよりも、それのコンテナーであるブラウザーの問題のような感じもします。ありがちなのは、ブラウザーが出すモーダルななんらかのダイアログボックスがウィンドウの裏に隠れている場合があります。

なお、Thread の run が呼ばれていなくても Thread はちゃんとできているのかを確認するためには、Thread を new する際に名前を付けてみてはどうでしょうか。
そうすれば、Java Console での際に名前で存在を確認できます。
http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/lang/Thread.html#Thread(java.lang.Runnable,%20java.lang.String)
などです。
rika
会議室デビュー日: 2004/02/23
投稿数: 4
投稿日時: 2004-02-25 11:31
unibon様、回答ありがとうございます。

>Java Applet 側の問題というよりも、それのコンテナーであるブラウザーの問題のような感じもします。

アドバイスをもとに検証した結果、原因らしい箇所を見つけることができました。ありがとうございます。

原因としては、Applet を呼び出している HTML側の JavaScript から ページの OnLoad 時に JavaApplet のメソッドを呼び出して値を渡している所があるのですが、そこと Applet側でスレッドを生成してスレッドスタートをしたときが重なったら、止まるようでした。
(もしかして、JavaScript からグローバル変数に値を書き込んでいるときにスレッドがスタートして run が呼ばれて、その中でグローバル変数を参照したから止まったのかなぁ?ロックしてないし・・・。)

こんな感じのソースです。

  // グローバル変数
  String wok[] = new String[8];

  public void start(){
    System.out.println( "start呼ばれました" );

    /** スレッドを起動 **/
    if( thr == null ){
      thr = new Thread( this );
      System.out.println( "スレッド生成開始 thr.start()" );
      thr.start();
      System.out.println( "スレッド生成終了 thr.start()" );
    }
  }

  public void run(){
    System.out.println( "run呼ばれました" );
    Thread thisThread = Thread.currentThread();

    while( thr == thisThread ){
     
      // ここで参照
      if( wok[cnt] != null ){

        // 処理

      }
    }
  }

  // JavaScriptから参照するメソッド
  public void SetImgName( String name, int camno, String mode ){
    System.out.println( "SetImgName 開始 name=" + name );
    wok[camno] = name;
    System.out.println( "SetImgName 終了 name=" + name );
  }

 止まったときのJavaコンソール
  init 開始
  init 終了
  start呼ばれました
  スレッド生成開始 thr.start()
  SetImgName 開始 name=...
  SetImgName 終了 name=...
 ここで止まっていましたので、上記のように考えました。

で、対策として start() が呼ばれたときに スレッドを生成する前に JavaScript から値がきているかを確認して(値が入るまで待つ)、その後スレッドを生成してスタートさせるようにしました。

どなたか原因が推測でもいいので、お分かりになられるようでしたらぜひ教えてください。よろしくお願いします。
 
Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2004-02-26 02:46
rikaさん、こんにちは。

runって表示してるかは兎も角として、

試しに,ループの中に Thread.sleep() とか入れてみて下さい。

例)
コード:

while( thr == thisThread ){
try {
Thread.sleep(100);

// ここで参照
if( wok[cnt] != null ){
// 処理
}
} catch (InterruptedException ex) {
// 必要なら、何かの処理
}
}



※この実験を行う前に、ブラウザを再起動してください。

[ メッセージ編集済み 編集者: Kissinger 編集日時 2004-02-26 02:48 ]
rika
会議室デビュー日: 2004/02/23
投稿数: 4
投稿日時: 2004-02-26 09:52
Kissinger様、ご回答ありがとうございます。

すみません、すでに Thread.sleep は、Kissinger様の書いてある通り
while文 のすぐ下に入っています。

  while( thr == thisTread ){

    try{
      thr.sleep(100);
    }
    catch(InterruptedException ex){
      System.out.println( "sleep中にスレッド終了しました" );
      return;
    }

    if( wok[cnt] != null ){

    }
  }

でも、私のソースでは、Sleep の例外しかキャッチしないので、Kissinger様のソースのように他の例外もキャッチできるようにしてみます。

ありがとうございました。
1

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