スレッドと同期

  1. 同期
    対戦型ゲームをおこなうとき、相手側の実行終了を待ち合わせる必要があります。相手の実行をボタンで知らせる場合、このボタンイベントに「同期」をかける必要があります。

  2. スレッドの同期

    1. スレッドの待ち合わせ
       スレッドに同期機能があります。スレッドで wait() を実行すると、notify(); が別のスレッドから実行されるまで、スレッドは実行を停止します。同期処理を行うメソッドの宣言には、synchronized を付加する必要があります。

         synchronized  public void waitButton(){
            try{
                 wait();
            }catch( InterruptedException e){}
          }
    2. 同期(待ち合わせ解除)
       wait() で待ち合わせ状態のスレッドを再開するには、notify() (「通知する」の意味) を実行します。notifyを実行するスレッドにも synchronized が必要です。
       synchronized public void step(){
          notify();
       }

  3. プログラム構成

    1. プログラム構成
       ここでは、メインスレッドとなるアプレットクラス sync と、メインスレッドから起動されるスレッドを定義する クラスproc の二つのソースファイルに分割して記述します。
       syncクラスでは、まず、init() で結果を表示するラベルと次のステップに進む「step」ボタンを生成します。次に、start()クラスで、proc クラスを生成し、スレッドの実行を開始します。

    2. procクラス
      1. Threadクラスの継承
        このクラスは、 次のように、Tread クラスを継承しています。
         public class proc extends Thread
        これは、
         Javaでは クラスの継承は一つに限定されるため、
         public class extends Applet, Thread
        のような、複数の継承はできません。
         それで、Threadの インターフェース版 である、 Runnable を
         public class extends Applet, implements Runnable
        として組み込んでいます。
         
      2. run( )
         スレッドでは、 run( ) メソッドの内容を、他のスレッドと並行に実行します。ここでは、ダミーの繰り返し処理を実行後、ラベルに * を追加し、waitButton(); を呼び出します。これは、スレッドの同期処理で「step」ボタンが押し下がられるまで、実行を休止します。
         対話型ゲームの場合、ダミーの部分でコンピュータ側の処理を実行します。ここで、人の処理を待ち、「step」ボタンが押されると、次の、繰り返しに進みます。

         public void run(){
              String st="";
              for(int i=0;i<10;i++){
                   for(int j=0;i<10000;j++){ 
                      //dummy 
                    }
                st +="*";
                main.msgLabel.setText(st);
                waitButton();
              }
               main.stepButton.setEnabled(false);
            }

  4. プログラム
    1. メインスレッド
      public class sync extends Applet{
          
          proc proc1;
          boolean alive=false;
      
          public Button stepButton = new Button();
          public Label msgLabel=new Label();
          
          public void init(){
              msgLabel.setText("textField1");
              msgLabel.setBounds(new Rectangle(20, 20, 100, 20));
              
              stepButton.setLabel("step");
              stepButton.setBounds(new Rectangle(40, 60, 70, 20));
              stepButton.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                  stepButton_actionPerformed(e);
                }
              });
              setLayout(null);
              add(msgLabel);
              add(stepButton, null);
          }
          
          public void start(){
              proc1=new proc(this);
              proc1.start();
          }
          
          void stepButton_actionPerformed(ActionEvent e) {
            proc1.step();
            //proc1.notify();
          }
      
      }

    2. 同期スレッド
      public class proc extends Thread{
              sync main;
      
              public proc(sync sync) {
                      this.main=sync;
              }
      
              public void run(){
                String st="";
                for(int i=0;i<10;i++){
                      for(int j=0;i<10000;j++){ 
                              //dummy 
                      }
                 st +="*";
                      main.msgLabel.setText(st);
                      waitButton();
                }
                main.stepButton.setEnabled(false);
              }
              
              synchronized  public void waitButton(){
                       try{
                               wait();
                         }catch( InterruptedException e){}
               }
      
               synchronized public void step(){
                 notify();
               }
      }
  5. 実行
    step ボタンを押すと * が一つ現れます。10回で終了します。




トップに戻る