プロが教えるわが家の防犯対策術!

よろしくお願いします。

 マルチスレッド下で動作するクラスを作成しています。データにアクセスするためのオブジェクトを
クラスのフィールド値として保持し、使い回しを行いたいと考えています。このデータアクセスオブジェクト(以下Dao)内では特にフィールドは使用せず、全てローカル変数のみで動作するようになっています。Dao自体は初回のクラス生成時にstatic処理にてフィールドにセットされます。

 このDaoを保持するフィールドは、staticなクラス変数が良いのか、インスタンス変数として保持する方が良いのか迷っております。

 クラス変数ならばPermanent領域をオブジェクト1つ分のメモリ使用で済み、インスタンス変数だとスレッド毎にheapを使い、処理数が増えるとメモリ圧迫しちゃう?と安易に考えてしまったりしています。

 ご意見・ご助言よろしくお願い致します。

A 回答 (5件)

staticフィールドはよいと思いますよ。

フィールド定義でオブジェクトを new するか、
static 初期子で初期化すれば、初期化時におけるスレッドの競合を避けられるので
問題ないし、全てのスレッドから可視のオブジェクトができます。

ただし、Daoオブジェクトがクラス変数もインスタンス変数も持たなくても
処理に必要な内部オブジェクトや外部への参照がスレッドセーフでない
可能性があるので注意が必要でしょう。

普通にシングルトンするという手もあります。
    • good
    • 0
この回答へのお礼

遅くなりましたが、ご回答ありがとうございました。

お礼日時:2013/03/03 14:05

>FactoryやSingletonのようなパターンを使用する場合、生成するオブジェクトをあらかじめstaticフィールドの変数として保持しておいて、それを返すといったcodeをよく目にします。


>どれも、実体は同じであるオブジェクトへの参照となるのですが、これもマルチスレッド下で使用することは危険と捉えるべきなのでしょうか?

以下ページの「まとめ」の「◎マルチスレッド環境での使用」を参照して下さい。
http://www.nulab.co.jp/designPatterns/designPatt …
    • good
    • 0
この回答へのお礼

遅くなりましたが、ご回答ありがとうございました。

お礼日時:2013/03/03 14:05

ちょっと勘違いがあるようなので


>FactoryやSingletonのようなパターンを使用する場合、生成するオブジェクトをあらかじめstaticフィールドの変数として保持しておいて、それを返すといったcodeをよく目にします。どれも、実体は同じであるオブジェクトへの参照となるのですが、これもマルチスレッド下で使用することは危険と捉えるべきなのでしょうか?

デザインパターンは、クラス設計のパターンなだけであり、スレッドセーフを保証する仕組みではありません。マルチスレッド環境でのスレッドセーフが要求される場合、独自に対応する必要があります。

あと、Javaではスレッドチェンジを抑制することはできません。
Synchronizedブロックを使用しても、オブジェクトにロックが掛かるだけです。

参考URL:http://www.ibm.com/developerworks/jp/java/librar …
    • good
    • 0
この回答へのお礼

遅くなりましたが、ご回答ありがとうございました。

お礼日時:2013/03/03 14:04

スレッドセーフなのは当然として。



staticにするか否かは、インスタンス数を決定することであり、インスタンス生成のコストにより決めます。
インスタンス生成のコストが深刻ならばシステムに付き1つ、
上限を設けたいならばオブジェクトのプーリング、
生成コストよりも処理数を上げるならば、インスタンス数は呼び出し側で決定するなどです。

私ならば、インスタンス変数にしてしまい、フレームワークでインスタンス数を決めます。
安易にstaticを使用すると、テストが困難になったり、再現性のないバグの元です。
    • good
    • 0
この回答へのお礼

遅くなりましたが、ご回答ありがとうございました。

お礼日時:2013/03/03 14:04

>マルチスレッド下で動作するクラスを作成しています。



だったらスレッドセーフに作らんとイカンだろ?

>staticなクラス変数が良いのか

staticなクラス変数は「誰かがこのクラスを既に使用中で、二重には使えない」って場合に、二重実行を監視する為に使う。

例えば、誰かがデータのレコードを読み込んで、一部だけ書き換えてアップデートする場合、アップデートが終わるまで、レコードを保持している変数と、書き換えたいレコードは「他のスレッドではアクセスしちゃいけない」のは自明。

そういう場合は「どのスレッドからも見える、ただ1つのフラグ変数」が必要になる。そのフラグが付いてたら「触るな」って事だから。

変数をstaticで置く場合は「その変数の使用開始から使用終了まで、一切、スレッドチェンジが起きない事」を保証しないといけない。

APIコールやOSコールを行うと、OSで勝手にスレッドチェンジが入るから「スレッドチェンジが起きない事」ってのは「APIコールやOSコールを一切使わず、CPUを占有する」ってこと(そして、そういうプログラムは忌避される)

マルチスレッドを軽く考えてると「思いもよらないバグ」で1~2ヶ月は泣かされる事になる。

この回答への補足

chie65535様

 丁寧なご回答ありがとうございます。自分の勉強不足を痛感しております。
 
 一点質問がございます。
 FactoryやSingletonのようなパターンを使用する場合、生成するオブジェクトをあらかじめstaticフィールドの変数として保持しておいて、それを返すといったcodeをよく目にします。どれも、実体は同じであるオブジェクトへの参照となるのですが、これもマルチスレッド下で使用することは危険と捉えるべきなのでしょうか?

 ご回答への質問となってしまい申し訳ございませんが、よろしくお願い致します。

補足日時:2012/12/18 01:57
    • good
    • 0
この回答へのお礼

遅くなりましたが、ご回答ありがとうございました。

お礼日時:2013/03/03 14:04

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!