痔になりやすい生活習慣とは?

http://itpro.nikkeibp.co.jp/article/COLUMN/20070 …

このサイトに以下ような趣旨の記述があり、信じられない気持ちでいっぱいです。
「マルチスレッドのケース(たとえばサーブレットでは、)インスタンス変数はヒープ領域に
保持されるので、複数のスレッドからアクセスされるので情報が書き換えられる場合がある」

信じられないのは、インスタンス変数が書き換えられるということです。
サーブレットではインスタンス変数が共有されるのは理解していますが、
サーブレットから呼ばれるインスタンスで定義されているインスタンス変数も
それに該当するのでしょうか。
それとも、サーブレット内だけの話で、サーブレットから呼ばれるインスタンスでは
インスタンス変数は独立していると思ってよいでしょうか。
後者の認識ですが、こういう書き方をされると、サーブレットから呼ばれた先でも
インスタンス変数が共有されると読めて、怖くて仕方ないです。

このQ&Aに関連する最新のQ&A

A 回答 (4件)

サーブレットから呼ばれるインスタンスをどの変数に格納するかによります。


サーブレットのインスタンス変数に格納したインスタンスがサーブレットから呼び出されるのであれば、呼び出されたインスタンスのインスタンス変数は共有されます。

これは記事のとおり、ヒープ領域に保持されたインスタンスの参照をたどるためです。

一方、ローカル変数に格納されたインスタンスは共有されません。
ローカル変数はヒープ領域ではなく、スタック領域に保持されるためです。

どうしてもローカル変数を使用する事ができず、インスタンス変数を使用しなければならないのであれば、ThreadLoacl クラスの使用を検討されてみてはいかがでしょうか。

参考URL:http://java.sun.com/javase/ja/6/docs/ja/api/java …
    • good
    • 0
この回答へのお礼

やはりそうでしたか。
ありがとうございました。

お礼日時:2011/01/11 13:28

一部不備がありましたので、訂正させて頂きます。



「一方、ローカル変数に格納されたインスタンスは共有されません。」

「一方、ローカル変数は共有されません。」

申し訳ありませんでした。
    • good
    • 0

> サーブレットから呼ばれるインスタンス



インスタンスを呼ぶことはできないので、質問者さんが何を意図しているのか分かりません。

> このサイトに以下ような趣旨の記述があり、信じられない気持ちでいっぱいです。

どうして信じられないのか分かりませんが、一般論としては全く正しいです。
あるインスタンスのインスタンス変数を書き換えるためにはそのインスタンスへの参照を持っている必要があります。したがって、あるスレッドで生成したインスタンスを他のスレッドから書き換えられないようにするには、そのインスタンスへの参照を他のスレッドに見せなければいいだけです。
    • good
    • 0
この回答へのお礼

まったくもって間違った回答ですね。
サーブレットからインスタンスを呼ぶことができないなんて・・・。

お礼日時:2011/01/11 13:15

>サーブレット内だけの話で、サーブレットから呼ばれるインスタンスでは


>インスタンス変数は独立していると思ってよいでしょうか。

どういう意味でしょうか? サーブレットから何かのインスタンスを利用している場合、その中のフィールド(インスタンス変数)はスレッドごとに独立しているか?ということですか。そんなわけはありません。すべてのスレッドでもちろん共有されます。あるいは、そういう意味ではない?

>サーブレットから呼ばれた先でも
>インスタンス変数が共有されると読めて、怖くて仕方ないです。

よくわからないのですが……、なにがどう怖いのでしょう。サーブレットのフィールドが各スレッドで共有されていることは理解されているのですよね……。具体的にどういうことを懸念されているのかがよくわからないのですが。
    • good
    • 0
この回答へのお礼

No3の方の回答がやはり正のような気がします。
自分でPGを書いてテストしても、No3の方のようになります。
ですので、以下の回答は間違いですね。

>サーブレットから何かのインスタンスを利用している場合、その中のフィールド(インスタンス変数)
>はスレッドごとに独立しているか?ということですか。そんなわけはありません。すべてのスレッドで
>もちろん共有されます。

念のため質問内容が分かるようなソースをつけます。
SampleClassで定義されているメンバー変数(staticではない変数)が、
スレッド毎に共有されるかという質問です。

servletclass extends HttpServet{
  public int a = 0;

public void doPost(){
SampleClass sc = new SampleClass();
}
}

SampleClass{
public int x = 0;
}

このようなプログラムがあったとします。
このプログラムを複数の人が、同時にアクセスした場合に、
SampleClassで定義されているメンバー変数のxが共有されるかという意味です。
もちろん、共有されないという認識です。

お礼日時:2011/01/11 13:24

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qマルチスレッド下でのインスタンス変数・クラス変数

よろしくお願いします。

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

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

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

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

Aベストアンサー

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

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

普通にシングルトンするという手もあります。

Qinterface,extend,implementのちがい

お世話になります、

Javaを勉強しているのですが、
interface,extend,implementの使い分けがわかりません。

私の解釈としては、
(1)interfaceは、グローバル変数の定義、グローバルメソッドの定義(実装はしない)。

(2)extendは、extendクラスを親クラスとして親クラスの機能を使用できる。

(3)implementは…,implementもextendと同じような意味だと解釈しているんですが、違う点は、implementで定義してあるメソッドは、使用しなくても、実装しなければならないという点でしょうか?

とにかくこの3つのを使い分けるコツとかあれば教えてください。
よろしくお願いします。

Aベストアンサー

バラバラに理解してもしょうがないッス。

まず、
(1)interface と implements
(2)class と extends

が対応しているわけっす。

JavaはC++と違って、比較的言語仕様を「簡単」にしたので「多重継承」という
概念がないです。
多重継承っていうのは、複数のクラスを親クラスにして継承するってことですね。

たとえば、 「TextFieldクラス」と「Japaneseクラス」を多重継承すると、
「JTextFieldクラス」ができるっていうのが自然な考え方でしょう?

まぁ、例えば、日本語クラスであれば、getStringLength()メソッドなどが
あったほうが良いでしょうか。
このgetStringLength()メソッドは、2バイト文字も1バイト文字も「1文字」
と数えてくれると言う点で、まさに、日本語クラス用のメソッドだと言えるでしょう。

例えば、Java的に記述すると、、、
class Japanese {
public int getStringLength() {
  ・・・
return strlength;
 }
 ・・・
}

class TextField {
・・・
}

class JTextField extends TextField, extends Japanese {
・・・・
}

C++ではそのように実装するでしょう。
しかし、Javaにはこのような高度な機能はありません。

そこで、生まれた苦肉の策が、「interfaceとimplements」です。

interface Japanese {
public int getStringLength(); // interfaceは実装を含まない!
                 // すなわち「実装の継承」ができるわけではない。
}

class TextField {
・・・
}

class JTextField extends TextField implements Japanese {
・・・・
public int getStringLength() {
  ・・・
return strlength; //implementsの実装を「各クラスで」実装してやる必要がある。
 }
}


結局のところ、Javaでは、複数のクラスを親クラスには持ち得ないため、継承できなかったクラスは「各クラスで実装してやる必要性」があるのです。


ではどのように使うのが効果的か?

なまえのままです。「代表的なインターフェイス」にたいしてinterfaceを使うのが良いと思います。

例えば、プレイヤー系であれば、ビデオ・コンポ・ウォークマン・などにかかわらず、
interface controlpanel {
public play();
public stop();
public next();
public back();
}
というような基本的インターフェイスを「持っているべき」です。

こうすることで、それぞれのクラス宣言の際に、これらの「インターフェイスを持っているべきであり、実装されるべきである」ということを「強く暗示」することができます。
class videoplayer extends player implements controlpanel {
public play() {・・・}
public stop() {・・・}
public next() {・・・}
public back() {・・・}
}

こうすることで、同様のクラスを作成するユーザーは、
「プレイヤー系は、4つ操作が出来るコントロールパネルをインターフェイスとして持つべきなのだな!?」という暗示を受け取り、自分のクラスでもそれを模倣するでしょう。

class mp3player extends player implements controlpanel {
public play() {・・・}
public stop() {・・・}
public next() {・・・}
public back() {・・・}
}

また、これらのクラスを使用するユーザーも、「implements controlpanel」という
表記を見て、「4つの基本操作は押さえられているのだな!」という基本中の基本動作を抑えることが出来ます。

まとめると、クラスに「こういう特徴もたしてください!」「こういう特徴持ってますよ!」という一種の暗示的警告や方向性を与えることができるわけですね。

バラバラに理解してもしょうがないッス。

まず、
(1)interface と implements
(2)class と extends

が対応しているわけっす。

JavaはC++と違って、比較的言語仕様を「簡単」にしたので「多重継承」という
概念がないです。
多重継承っていうのは、複数のクラスを親クラスにして継承するってことですね。

たとえば、 「TextFieldクラス」と「Japaneseクラス」を多重継承すると、
「JTextFieldクラス」ができるっていうのが自然な考え方でしょう?

まぁ、例えば、日本語クラスであれば...続きを読む

QServletにおけるスレッド間でのグローバル変数の関係

お世話になっております。

サーブレットクラスにて定義したグローバル変数へ、それぞれ別のスレッドからアクセスした場合、
それぞれの値には関連性が無いと認識していたのですが、それは誤りでしょうか?

グローバル変数を有するサーブレットクラスを作成し、2つのスレッドを流したところ、1つ目のスレッドでセットした値が、後追いで流した2つ目のスレッドでセットした値に置き換わってしまいました。

それぞれの値を関連性の無いようにしたいのですが
どのようにしたら良いのか、ご存知の方いらっしゃいましたらご教授願います。

宜しくお願い致します。

Aベストアンサー

その他の方法では
SingleThreadModelを実装する。

このパターンですと
リクエストごとにインスタンスを
生成するようになります。

方法は
public class Sample extend HttpServlet
    implements SingleThreadModel {
です。

QServletからServletへの値渡し

最近、A-ServletからB-Servletへの遷移は

response.sendRedirect("B-Servlet");

で可能だと教えて頂きました。

ですがもうひとつわからないことがあります。
このときに、B-Servletへ変数を渡したいのですがやり方がわかりません。
わかる方教えてください><

Aベストアンサー

こんにちは。world99です。 sin-da4のご認識の通りでした。
 doGet()で呼び出されたサーブレットから次のサーブレットに遷移する時は、doGet()が実行されます。同じように、doPost()で呼び出されたサーブレットは、doPost()で次のサーブレットを呼び出します。
 実は、私が試したサンプルは、doGet()とdoPost()のどちらが呼び出されても、doProcess()というメソッドを実行するように、実装しています。文章を短くするための、それを端折っていました。という訳で、この事に気がつきませんでした。
 教えているつもりだった私が逆に、教えて頂きましたねありがとうございます。orz
 あるServletから別のServeltに遷移する時に、値を引き渡すという本題の質問は、これで解決ですね♪

Qスレッドとプロセスの違い

今晩は。
早速ですが、javaのプログラムを勉強中です、スレッドとプロセスどう違うのでしょうか。
本などを読んでいろいろと調べましたが良く分かりません、宜しくお願いします。

Aベストアンサー

がると申します。
とりあえずまず「スレッドとプロセスは違うモノ」です。

で、簡単に………というのはちと難しいのですが、出来るだけかみ砕いて説明を。
ただ、どうしても深い部分を触らないといけないので、そのあたりご勘弁ください。

まず「マルチタスク」という概念があります。
基本的に、1つのCPUしか乗っていないPCの場合、ある1つの時間軸には1つの処理しかできません。当然ですが。
ただ、その「1つの処理」にかかる時間はとても小さいので「擬似的に」複数の処理が並列で走っているように見せかける事ができます。
この辺をマルチタスク、なんて呼称してました(過去形にしていいのかは微妙ですが、実際現場でこの単語を聞く事がきわめてレアなので)。
で、このマルチタスクを別名「マルチプロセス」なんて言い方もしました。

で。とりあえず見せかけ上ではあるものの、各プロセスは「平行して」動いているわけです。
で、ここで問題になるのが「ある1プロセスがとてつもない悪さをしてメモリをがりんがりんと変に書き換えたとき」という状況があります。
で、そういった状況をなくすために、通常OSレベルで、各プロセスに「プロセス空間」というものを割り当てます。割り当てる資源はメモリなのですが。
この「プロセス空間」のおかげで、ド最悪「お行儀の悪い」プログラムを実行しても、周りのプログラムを巻き添えにせずにすみます。

ここまでが大雑把にプロセスのお話です。

さて。問題がありまして。
プロセスを1つ立ち上げるためには、当然ながら「プロセス空間を切り出してそれを割り当てて」という処理が自動で走ります。プロセスが一つ死ぬときはもちろんその逆が。
…この処理が、なかなかに重いのです(特にSolaris)。
また、プロセスは空間をそれぞれ隔てているために、「不可侵」であるには便利なのですが、「データをやりとり」したいときはある程度面倒です(この辺興味が有れば「プロセス間通信」でご検索を)。
そこで生まれたのがスレッドです。
スレッドは、1プロセスの中に複数生成できます。また、1プロセス内であるために、基本的にメモリを共有しています。
そのために…
・プロセスと比較して、スレッドの生成は処理コストが安い
・メモリを共有しているので、プロセス間通信と比較して、やりとりがしやすい
などのメリットがあります。
なお、2番目のメリットはそのままデメリット化しますので(この辺はスレッドセーフなどのキーワードでご検索ください)ご注意のほどを。

このあたりは…多分言語としてのJavaを学ぶだけだと、ちょっと手に入りにくい部分なのかもしれないのですが。
ちょっとだけ手をひろげて、いろいろな技術書を読むと出てくるかもしれません。

以上なにかの参考にでも成れば幸いです。

がると申します。
とりあえずまず「スレッドとプロセスは違うモノ」です。

で、簡単に………というのはちと難しいのですが、出来るだけかみ砕いて説明を。
ただ、どうしても深い部分を触らないといけないので、そのあたりご勘弁ください。

まず「マルチタスク」という概念があります。
基本的に、1つのCPUしか乗っていないPCの場合、ある1つの時間軸には1つの処理しかできません。当然ですが。
ただ、その「1つの処理」にかかる時間はとても小さいので「擬似的に」複数の処理が並列で走っているように...続きを読む

QArrayListを使った多次元配列の作成について

ArrayListで可変長配列を扱っているのですが、
2次元可変長配列を用いる必要が出てきたので、
下記のように変更したのですがうまくいきません。
何が悪いのか教えていただけませんでしょうか?

-----------------------------------------
ArrayList cars=new ArrayList();
cars.add("フェラーリ");
cars.add("ポルシェ");
cars.add("メルセデスベンツ");
for(int i=0;i<cars.size();i++){
 String str=(String)cars.get(i);
 System.out.println(str);}
-----------------------------------------
上記から下記のように変更しました。
-----------------------------------------
ArrayList[] cars=new ArrayList[3];
cars[0].add("フェラーリ");
cars[0].add("ポルシェ");
cars[0].add("メルセデスベンツ");
for(int i=0;i<cars[0].size();i++){
 String str=(String)cars[0].get(i);
 System.out.println(str);}
-----------------------------------------
エラーは「Exception in thread "main" java.lang.NullPointerException」です。
どうやら初期配列が10ではなく3となってしまっているようです。

ArrayListで可変長配列を扱っているのですが、
2次元可変長配列を用いる必要が出てきたので、
下記のように変更したのですがうまくいきません。
何が悪いのか教えていただけませんでしょうか?

-----------------------------------------
ArrayList cars=new ArrayList();
cars.add("フェラーリ");
cars.add("ポルシェ");
cars.add("メルセデスベンツ");
for(int i=0;i<cars.size();i++){
 String str=(String)cars.get(i);
 System.out.println(str);}
---------------------------------------...続きを読む

Aベストアンサー

こんにちは。

>ArrayList[] cars=new ArrayList[3];
はArrayList型のオブジェクトのインスタンス
を格納する箱を3個作成しただけなので、
この時点では、
cars[0] = null
cars[1] = null
cars[2] = null
となっています。ですから、当然
cars[0].add("フェラーリ");
などとやると、NullPointerExceptionが
発生します。これをさけるには、
cars[0] = new ArrayList();
cars[1] = new ArrayList();
cars[2] = new ArrayList();
とする必要があります。

QMAX値を条件にデータを取得するには?

SQL文で困っています。
ご教授下さい。


下記のようなデータがあった場合、それぞれの区分毎に
年月が最大(最新)のデータを取得したいです。
(実際には1レコードにその他項目があり、それらも取得します。)
<検索対象データ>
区分 年月   金額
-----------------------------
A   200412  600
A   200503  560
B   200311  600
B   200508  1000
B   200504  560
C   200508  400
C   200301  1100


<取得したいデータ>

区分 年月   金額
-----------------------------
A   200503  560
B   200508  1000
C   200508  400

よろしくお願いします。

Aベストアンサー

テーブル名をXXXとすると次のようなSQLでよいと思います。(最善の方法かどうかは自信がないですが)

select B.* from (select 区分, max(年月) as 年月 from XXX group by 区分) As A
inner join XXX as B on A.区分 = B.区分 and A.年月 = B.年月
order by B.区分

Qエクセルで作成した表内で、文字の上に訂正線を引くには??

表題のとおりです。

エクセルでセル内にある文字の上に、訂正(修正)線を引きたいのですが、まったくどうしていいものかわかりません!!

初心者です!

どなたか教えてください!!

Aベストアンサー

puerariaさん

>そうすると、選択したセル内の全ての文字に取り消し線が入りますよね??
その通りですね。部分的に取り消し線を入れることは可能です。
その場合、次の手順を踏んでください。

1.対象のセルをダブルクリックするなどして、中の文字列を選択出来る状態にして下さい。
2.取消線を入れたい文字列をマウスなどで反転させてください。
3.反転した文字列の上で右クリックした後、セルの書式設定を選択。
4.左下に有る取消線をチェック後にOKです。


人気Q&Aランキング