- PR -

オブジェクトの参照について

投稿者投稿内容
ペンギン
会議室デビュー日: 2002/04/14
投稿数: 10
投稿日時: 2002-04-18 14:00
しっくりくる質問の名前が思いつかなかったのですが、
下記のようなサンプルで、B が A の hash の参照を
フィールドに保持しているという状態を A が知ることはできますか?
getHashで「取得中です」というフラグを A に持たせ、
B が使い終わったら、A のフラグを変更するような作りしかないですか?

コード:
class A {
  public static Hashtable hash = new Hashtable();
  public static Hashtable getHash(){
    return hash;
  }
}

class B {
 public Hashtable hash;
  public void main(){
    hash = A.getHash();
  }
}

miki
大ベテラン
会議室デビュー日: 2001/09/21
投稿数: 174
お住まい・勤務地: 東京都八王子市
投稿日時: 2002-04-18 17:50
WeakHashMapが使えるかもしれません。
(かもしれないと書いたのは、私は実際に使いこなしていないからです)

質問の本当の目的がわからないのですが、Aのhashがメモリを圧迫するのでユーザが一人もいなければ解放したい、ということならWeakHashMapにAのhashを登録するだけでよいと思います。誰もそのhashを参照していなければGCが解放してくれるはずです。
ペンギン
会議室デビュー日: 2002/04/14
投稿数: 10
投稿日時: 2002-04-18 23:05
ご返答ありがとうございます。

>質問の本当の目的がわからないのですが、Aのhashがメモリを圧迫するのでユーザが
>一人もいなければ解放したい、ということならWeakHashMapにAのhashを登録する
>だけでよいと思います。誰もそのhashを参照していなければGCが解放してくれる
>はずです。

すみません、ちょっと違います。
実際には Hashtable ではなく自前クラス(仮にXXXとします)なんです。
ユーザがXXXのいくつかのメソッドを、割と長い時間をかけて実行します。
各メソッドにはsynchronizedがかかっているので、
同時に複数のユーザがいても、不整合がおきないようになっています。
このとき、XXXの提供元クラスで、各ユーザが使い終わってから、
XXXの状態をクリアするメソッドを実行したいのです。

(初めから、こう書けばよかったですか・・・)

返答を見て、初めてWeakHashMapをリファレンスで引いてみました:oops:
削除したくなった段階で、WeakHashMapに入れてやると、
ユーザが使い終わったら、GCが開放してくれるということでしょうか?
ほったらかしにするよりは、確実に(早く?)削除されるのでしょうか?
WeakHashMapの説明は自分にとっては難解でした・・・。
H2
ぬし
会議室デビュー日: 2001/09/06
投稿数: 586
お住まい・勤務地: 港
投稿日時: 2002-04-19 06:29
こういうのは?
コード:
class A {
  private static XXX xxx = new XXX();
  private static Object owner = null;

  synchronized public static XXX checkOutXXX(Object owner) {
    if(owner==null) {
      this.owner = owner;
      return xxx;    
    }
    return null;
  }

  public static void checkInXXX(XXX xxx) {
    if(xxx==this.xxx) {
        owner = null;
    }
  }
}

class B {
 private XXX xxx;
  
  public void main() {
    
    try {
      xxx = A.checkOutXXX(this);  

      /*xxxを使った処理*/

    } finally {
      /*どんな場合でもxxxを返す*/
      A.checkInXXX(xxx);
      xxx = null;
    }
  }
}


checkInXXX()とcheckOutXXX()でオブジェクトの管理をすれば良いわけです。これなら、他からのxxxオブジェクトのアクセスもcheckOutXXX()で制限されますので、他のメソッドにsynchronizedもなくても良いはずです。よって多少の排泄処理にかかるオーバーヘッドを減らせるはずです。(うーん。正しいですよね?)

この方法ならどのオブジェクトがxxxを参照してるか分かります。ただ欠点としては、checkOutXXX()後でもclass BのxxxはClass Aのxxxへの参照を保持しているので、明示的にnullへ変える必要があります。(これなんとかならないでしょうか?)
YOU@IT
ぬし
会議室デビュー日: 2002/03/29
投稿数: 284
お住まい・勤務地: 大阪
投稿日時: 2002-04-19 09:21
>>ペンギン様

まず、仕様の確認なのですが、
提供元インスタンス(以降A)が保持するXxxのインスタンスへの参照を、利用者側インスタンス(以降B)が取得してXxxのメソッドを利用するわけですね?
で、Xxxのメソッドに排他制御がかけられているということは、Xxxインスタンスは複数のBインスタンスから共有されると・・・(XxxはSingletonパターン?)
さらにXxxインスタンスのフィールドに各メソッドの処理結果か何かが残るので、次のB’インスタンスから利用される前にそれをクリアしたい。
・・・と言う事でしょうか?

処理のフロー的には以下のような感じでしょうか?
1.A内でxxxを生成する。
2.BがAからxxxの参照を取得する。
3.Bがxxxのメソッドを実行する。
4.Bの処理終了後、次の利用に備えてxxxをクリアする。
5.B’がAからxxxの参照を取得する。
6.B’がxxxのメソッドを実行する。
7.B’の処理終了後、次の利用に備えてxxxをクリアする。
・・・以降繰り返し。
で、4と7のクリア処理をどこで実行するか?が問題ですね。

もし、上記のような仕様であれば、そもそもXxxの参照をB(B’)が取得する事自体が間違っているのではないでしょうか?

ペンギン様が最初に提示されたサンプルコードを見ても、AがXxxのインスタンスを管理する言わばマネージャとしての役割を持っていると思います。
であれば、BがXxxのメソッドを直接実行するのではなく、AがXxxのメソッドをラップしてBに公開し、BはAのメソッドを利用するほうが、Aに制御が集中していいと思うのですが。

ちょっとわかりにくい文章かもしれませんが・・・
要はクラスの責任が明確になっていないのでは?と言う事を言いたいわけです。
外していたらごめんなさい
YOU@IT
ぬし
会議室デビュー日: 2002/03/29
投稿数: 284
お住まい・勤務地: 大阪
投稿日時: 2002-04-19 09:33
あ、もう一点補足です。

>ユーザがXXXのいくつかのメソッドを、割と長い時間をかけて
>実行します。
と言う事は、Xxxのいくつかのメソッドがひとまとまりになって1つのトランザクションになっているのではないですか?

>各メソッドにはsynchronizedがかかっているので、
>同時に複数のユーザがいても、不整合がおきないようになっています。
上記のようにトランザクションとして処理されるのであれば、個々のメソッドをsynchronizedにしても、トランザクションのASID属性は守られません。

>このとき、XXXの提供元クラスで、各ユーザが使い終わってから、
>XXXの状態をクリアするメソッドを実行したいのです。
トランザクションの観点から見ても、やはりクラスAでXXXのメソッドをラップする形で1トランザクションを実行するメソッドを提供すべきではないかと思えるのですが。

Ex)
class A{
private static XXX xxx;

static{
xxx = new XXX();
}

/**
* XXXのいくつかのメソッドをまとめて、1トランザクションをして提供する
*/
pubic static void executeTransaction(Object param){
xxx.firstMethod(param);
xxx.secondMethod(param);
xxx.thirdMethod(param);
xxx.clear();
}
}


class B{
public static void main(String[] args){
A.executeTransaction(new SomeObject());
A.executeTransaction(new SomeObject());
}
}

YOU@IT
ぬし
会議室デビュー日: 2002/03/29
投稿数: 284
お住まい・勤務地: 大阪
投稿日時: 2002-04-19 09:36
ごめんなさい、
ASID属性 → ACID属性
です。

# 無駄なレスをしてしまってスミマセン
しょむ
ぬし
会議室デビュー日: 2001/09/06
投稿数: 430
投稿日時: 2002-04-19 09:44
この要件って、タスクキューというのでは…
実装が面倒なら TimerTask を使えないかな…

あと、参照の話なら、クラスではなくインスタンスでお話ししないと混乱します。
余談ですが、WeakReference というのもあったりして。

[ メッセージ編集済み 編集者: しょむ 編集日時 2002-04-19 09:46 ]

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