紙コップ

オブジェクトのロックのテスト

2009-02-19 12:56:01

Javaは言語レベルでマルチスレッド化されています。ただし、マルチスレッドであるからこそ、適切に同期をとる必要があります。今回は、オブジェクトのロックのテストをやってみました。



今回のサンプルプログラムの動きは以下のような感じです。



・オブジェクトのロックをテストする本体プログラム「ObjLockTest」

・ロックされる対象として、特定のサイトのHTMLソースコードを取得して行数を返すオブジェクト「HttpCliet」を作成

・HttpClientがきちんと行数をカウントし終えるまで本体ObjLockTestが待機できるかどうか試してみる。



では、ソースコードです。



■Javaソースコード(ObjLockTest.java)

/**

* オブジェクトのロックのテスト

*/



public class ObjLockTest {

  public static void main(String[] args) {

    HttpClient hc = new HttpClient();

    Thread t = new Thread(hc);

    t.start();

    

    //HttpClientのロックを取得

    synchronized(hc) {

      try {

        System.out.println("HttpClientの処理の終了を待ちます。");

        //HttpClientのロック開放を待つ

        hc.wait();

        

        System.out.println("HttpClientの処理が終了しました。");

      } catch(InterruptedException e) {

        System.out.println("" + e);

      }

    }

    

    System.out.println("HTMLソースコードの行数:" + hc.getCnt() + "行");

  }

}





■Javaソースコード(HttpClient.java)

/**

* 「http://aquasoft.exblog.jp」のHTMLソースコードを取得して、

* その行数を返すクラス

*/



import java.net.*;

import java.io.*;



class HttpClient implements Runnable {

  private int cnt;

  public void run() {

    synchronized(this) {

      BufferedReader reader = null;

      try {

        URL url =

          new URL("http://aquasoft.exblog.jp");

        HttpURLConnection huc =

          (HttpURLConnection) url.openConnection();

        reader =

          new BufferedReader(

            new InputStreamReader(huc.getInputStream())

          );

        while(reader.readLine() != null) {

          //行数のカウント

          cnt++;

        }

      } catch(MalformedURLException e) {

        System.err.println("" + e);

      } catch(IOException e) {

        System.err.println("" + e);

      } finally {

        try {

          reader.close();

        } catch(IOException e) {}

      }

      

      //ロックの開放を待機オブジェクトに通知

      notify();

    }

  }

  public int getCnt() {

    return cnt;

  }

}





ブログ内でのソースの読みやすさを考え、ちょっと気持ちの悪いところで折り返しています。ご勘弁を。



実際に動かしてみると、こんな感じです。







行数の取得は思ったよりも早く終わります。きちんと行数を取得できていますね。synchronizedブロックで対象のオブジェクトのロックを取得し、wait()メソッドでロックの開放を待ちます。



対象のオブジェクトは自身のsynchronizeブロック内で自分自身のロックを取得し、他のオブジェクトがsynchronizeブロック内にアクセスする事を排他します。



目的の処理が終わったらnotify()メソッドで、待機中のオブジェクトにロックの開放を通知します。他のオブジェクトはロック開放の通知を受け取り次第、「実行可能状態」になります。ただちに「実行状態」になるわけではないのがポイントです。実行可能な状態にはなりますが、はたして通知を受けたどのオブジェクトが実際に実行されるかは、JVM任せになり、プログラマは把握できません。



ここで、仮に、本体側のsynchronizeブロックをコメントアウトすると、どうなるでしょうか?当然、行数のカウントが終わる前に、行数を表示する行に到達してしまうはずですよね。



試してみましょう。



■Javaソースコード(ObjLockTest.java)

(※synchronizeブロックをコメントアウトしてみる)

/**

* オブジェクトのロックのテスト

*/



public class ObjLockTest {

  public static void main(String[] args) {

    HttpClient hc = new HttpClient();

    Thread t = new Thread(hc);

    t.start();

    

    //HttpClientのロックを取得

    //synchronized(hc) {

      //try {

        System.out.println("HttpClientの処理の終了を待ちます。");

        //HttpClientのロック開放を待つ

        //hc.wait();

        

        System.out.println("HttpClientの処理が終了しました。");

      //} catch(InterruptedException e) {

        //System.out.println("" + e);

      //}

    //}

    

    System.out.println("HTMLソースコードの行数:" + hc.getCnt() + "行");

  }

}





当然、こうなります。







この記事が、参考になった、面白かったという方はクリックをお願いいたします!





[ブログ内検索用キーワード]

Java スレッド ロック 同期 synchronized wait() notify

※このエントリは ブロガーにより投稿されたものです。朝日インタラクティブ および ZDNet Japan編集部の見解・意向を示すものではありません。
  • 新着記事
  • 特集
  • ブログ
このサイトでは、利用状況の把握や広告配信などのために、Cookieなどを使用してアクセスデータを取得・利用しています。 これ以降ページを遷移した場合、Cookieなどの設定や使用に同意したことになります。
Cookieなどの設定や使用の詳細、オプトアウトについては詳細をご覧ください。
[ 閉じる ]