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

Javaカテゴリでお訊きすることではないとも思うのですが、今、Javaを勉強中で、その中でもマルチスレッドの段階に入ってきたので、こちらで質問させて頂きました。

インスタンスとスレッドって、要は何が違うのでしょうか。

当方はプログラミング歴自体は、C言語で仕事で10年以上やっていて、その中では、組み込みもやりましたから、当然マルチスレッド環境のソフトにも関わってきましたが、
スレッドの原理的な制御部分はできあがった状態でプロジェクトに参入することが多く、担当を任されたスレッドの中で(要は閉じた中で)の仕事経験しかありません。

そこにきて今、Javaをゼロから勉強してみると、あくまでインスタンスとスレッドは分けて表現されており、
私も本を読み進めてみて、感覚的にはわからないではないですが、ちょっと立ち入った説明になると、双方がごっちゃになりわからなくなってしまいます。

どなたかお教え頂けませんか。
Javaの文法的なことは一通り勉強しましたし、C言語の素地もあるので、難しめの話でも結構ですし、たとえ話でも結構です。よろしくお願いします。

A 回答 (9件)

> class Aaa extends Thread {


> private int i;
> public int j;
> public static int k;
> (略)
> }
> とあった場合、i,j,kが共有されるということですか?

Threadオブジェクトに固執すると分かり難くなる話なので良い例とは言い難いですが、オブジェクトへのアクセス手段を用意しておけば共有可能ですよ。実際のアクセス手段は静的変数を経由しないと用意できませんけど。そういった意味では静的変数を介してアクセスできるオブジェクトが共有の対象ですね。
例ではkはAaa.kでアクセスできるので別のスレッドからでも簡単にアクセスできますが、i,jは静的変数から直接間接にアクセスできるAaaクラスのインスタンスのメンバにしかアクセスできませんね。
実のところローカル変数が共有できないのは言語仕様的にアクセス手段を用意できないからですし。

閑話休題、ANo.7にも書きましたが、もう一度「プログラムがどのように動いているか」の理解を確認した方が良いですよ。
    • good
    • 1
この回答へのお礼

ご回答、ありがとうございます。

確かに、
>「プログラムがどのように動いているか」の理解を確認した方が良い
ですね。

C言語(GNUのC、OSはLinux)でやっていたときは、スレッドをクリエイトする標準関数と、それをスタートさせる標準関数をコールするだけでスレッドが生成されて、
そこに書かれたコードの通りに動き出す...という感じだったので、そうりゃあ、プログラムが増えるようなものだから、
rinkunさんが言われていたようにCPUもシェアして使われるだろうし、みたいなことは特に疑問もないというか、そんなもんだろなと自然に認識していましたが、

Javaの場合、コードから追うとそういうことが自然に理解できないんです。頭の中で切り分けができないというか。

今の私の理解では、Threadからextendsされたインスタンスには、インスタンスの中にスレッドのタネがあって、スレッドを発生させられる...というイメージしか浮かびません。

もの凄くヘンな比喩で恐縮ですが、人間の身体(インスタンス)の中には、長い小腸(スレッドとして動く場合にコールされるrun()みたいなイメージ)がありますが、
start()とやると、身体から勝手に小腸が飛び出して非同期で動き出す。 他の臓器のことは知らないよ! みたいなイメージです。

まあ、私もちょっと無理な勉強法をしてしまった反省があります。
最初に、有名な「やさしい」シリーズの「やさしいJava」で一通り勉強したあと、プログラミング歴だけは長いものですから、
いきなりこれまた有名な結城浩氏の「Java言語で学ぶデザインパターン入門(マルチスレッド編)」を読んで、読み進められはするものの、
「スレッドって要はナニ?病」に取り憑かれてしまいました。

もっとじっくり修行して参ります。

------------------------
私からは単独のコメントを付けられる仕組みは無いようですので、
rinkunさんへのレス場所を借りて、たくさんの親切なコメントを付けて下さった皆さまにお礼申し上げます。

結局、納得がいくまでには至りませんでしたが、キーとなる言葉は随分ありましたので、それを中心に修行したいと思います。
ありがとうございました!

お礼日時:2007/12/13 10:28

runはスレッドが起動したときに最初に呼び出されるメソッドというだけでスレッドとして動くメソッドではありません。

スレッドを起動しなくても普通にrunを呼び出すこともできますよ。
この辺はmainがプログラムの起動時に最初に呼び出されるメソッドだというのと同じです。

スレッド起動はある意味で新しいプログラムを起動しているのと同じです。ただそのプログラムが今までのと同じ変数を(ローカル変数を除いて全て)共有していてmainからでなくrunから始まるというだけで。

この回答への補足

何度もお答え、ありがとうございます。

>runはスレッドが起動したときに最初に呼び出されるメソッドというだけで
確かにそう書いてありますし、そのようになりますよね。
試しに強制的にrun()を呼び出したときはスレッドは発生しませんでした。

>ただそのプログラムが今までのと同じ変数を(ローカル変数を除いて全て)共有していて
すいませんが、ここの意味がわかりません。例えば、
class Aaa extends Thread {
private int i;
public int j;
public static int k;
//
public xyz() {
int a;
(略)
}
}
とあった場合、i,j,kが共有されるということですか?
??????....だから何なんだと(すいません口の利き方を知らなくて)思ってしまうのですが...

やばい...皆さん丁寧に答えてくださるのに、訊けば訊くほど混乱してくる............

補足日時:2007/12/12 12:30
    • good
    • 0

スレッドの実体ですか。


関数(メソッド)の呼び出し関係を保持するスタックと実行中のCPUレジスタ状態ですね。これらはコンテキストと呼ばれます。あとはそれを実行するCPU時間の割り当てです。
これらは全てプログラムの実行環境に用意されるものでコード上には見えません。そもそもプログラムがどのように動いているか、という部分の理解を確認した方が良いでしょう。

Thread#start内では、新しいコンテキスト(スタックとCPUレジスタ状態を保持しておくメモリ)を用意して、CPUレジスタ状態を現在のコンテキストを保存して新しいコンテキストのCPUレジスタ状態をCPUに読み込むことで新スレッドに切り替えます。
これによって新スレッドが走り始めます。
あとは、スレッドが一定時間走ったりIO待ちをしたりするタイミングで他のスレッドと切り替えつつ動作を続けるわけです。

この回答への補足

回答ありがとうございます。

なるほど、スタックやCPUレジスタなどのコアなリソース情報をコンテキストに格納し、コンテキストが複数の場合はCPUがとっかえひっかえ実行するというイメージですね。
だからたぶん、スレッド制御は便利な分、そういうとっかえひっかえ部分(スレッドの切り替え)でオーバヘッドタイムを取られたりして、時間がちょっとかかるとか言われるのでしょうね。
それはそれで分かる気がします。

ただ、その一方で、run()の中には、基本的に何とでもコードを書けて、よそのインスタンスのメソッドをコールしたりできますよね。
そして普通のインスタンスも、基本的に何とでもコードを書けて、よそのインスタンスのメソッドをコールしたりできますよね。

なにが違うんでしょう.................(なんか堂々巡りやな)

ああ、自分で書いててわかってきました。
インスタンスインスタンスと言いながら、その中にスレッドとして動くrun()があって、それが動くというところの整合性がわからないのです。

補足日時:2007/12/11 11:52
    • good
    • 0

 こんばんは。



>PecoPlusさんが書いてくださったコード(class Aaa implements
>~thread.start();まで)は、形式的な意味合いは理解しますが、
>正直、何でそういうコードになるのか、もっと言うと、
>implementsを使わずに、Threadから単純に継承したクラスと
>何が違うのかが、わからないです。

 前にも書きましたが、Threadを継承するやり方は、決して間違いではありません。
 ただし、私は、implements Runnableをする方が本来的で、あの一手間省く場合や本当にスレッドとそのインスタンスが強烈に関連している特殊ケースに対応するためにあとから作られたものではないかと感じています。
 まあ、この辺は宗教論争みたいになるので、強く主張するつもりはありません。

 動物のたとえは大嫌いなのですが、

class Dog extends Animal {}

 この場合、継承では、「Dog is a Animal.」「犬は動物である。」という is a の関係が成り立たなければなりません。
 いくら強い関連性があるからとはいえ、

class Dog extends 飼い主 {}

 これは、おかしいです。

 では、本当に「Aaa is a Thread」なのでしょうか?
 スレッドは、プログラムの実行者です。
 プログラムからはあたかもCPUがもう一つ増えたかのように見えます。
 つまり「Aaa is a 実行者(CPU)」と言えるでしょうか?

 私は、あの一手間を惜しむばかりに、かえってスレッドの学習に混乱をもたらしてしまったように思えます。

>くっついてるというより、一対一じゃないんですか?

 では、スレッドとインスタンスが一対一でない例を一つ。

Aaa aaa = new Aaa();
Thread thread1 = new Thread(aaa);
Thread thread2 = new Thread(aaa);
thread1.start();
thread2.start();

 これで、あっという間に一対一ではなくなりました。

 また、

class Aaa implements Runnable {
  Ccc ccc;
  Aaa(Ccc c) {
    ccc = c;
  }
  public void run() {
    ccc.hoge();
  }
}

class Bbb implements Runnable {
  Ccc ccc;
  Bbb(Ccc c) {
    ccc = c;
  }
  public void run() {
    ccc.hoge();
  }
}

Ccc ccc = new Ccc();
Aaa aaa = new Aaa(ccc);
Bbb bbb = new Bbb(ccc);
Thread threadA = new Thread(aaa);
Thread threadB = new Thread(bbb);
threadA.start();
threadB.start();

 これは、出てくるインスタンスは三つ。
 スレッドは二つ。
 しかも、cccは二つのスレッド両方に関連してきます。

 実際のプログラムでは、もっともっと複雑でたくさんのインスタンスやクラスが絡んできます。
 スレッドとインスタンスが一対一というのは、よほど単純なプログラムか、プログラマーがそれぞれのスレッドが他のインスタンスにちょっかいをかけないように、慎重に設計されている場合だけです。

この回答への補足

何度もお答え頂き、ありがとうございます。

うーん.........................
これを言うと話が拡がってしまうので控えていましたが、正直、implementsの意味がイマイチ分かっていません。
勿論、implements は和訳すれば「実装」であり、Runnableという純粋仮想クラスのようなクラスを実装しているのだ、ということはわかっています。

分かってはいますが、今まで何やるのでもさんざん extends でやってきたのに、なぜ突然 implements なわけ? ぶっちゃけ「今更なにソレ?」って感じです。
..すいません。 この話題はここで終わらせます。PecoPlusさんを振り回してしまいますし、自分はたぶんもっと分からなくなると思うので。

ただ「implements Runnableをする方が本来的」。この言葉をキーに、いろいろ調べてみようと思います。

>つまり「Aaa is a 実行者(CPU)」と言えるでしょうか?
言えませんよね。インスタンス(Aaa)は実行者ではありませんから。新聞と読者は同じではありませんから。
しかしだからどうだと......(ケンカ売ってんじゃないですよ、念のため)

それと、PecoPlusさんが「スレッドとインスタンスが一対一でない例を一つ」として示された5行のコードですが、これは結局、一対一ではないのですか?

なぜなら、thread1とthread2は別のインスタンスですから、thread1から生まれたスレッド(4行目)は、thread2から生まれたスレッド(5行目)とは関係ないわけで、
ということは、2行目と4行目は一対一で結びつき、3行目と5行目が一対一で結びつき、4行目と5行目はお互い関係ない...のではないでしょうか?
(この辺が根本的にわかってないのかな...)

そして最後に示された7行のコード。
たぶんこれは、Cccクラスの中に synchronized したメソッドなどを適宜用意して、必要なフィールドをガードし、共有資源である ccc が異なるスレッドからランダムにアクセスされた際に、適宜排他制御したりするケースのコードですよね。

このコードをタネにして、もっとたくさんのスレッドを発生させて、ランダムな時間間隔で、共有資源の必要なフィールドに排他制御しながらアクセスさせ、且つ、例えば10秒間アクセスがなかったら LivenessException例外を投げるようにしろ、と言われたらそういうコードも書けます。

しかしそれでも、  で?結局スレッドの正体はナニ? という疑問は消えません。

補足日時:2007/12/11 11:10
    • good
    • 0
この回答へのお礼

本当は補足欄に書いたことを、ここに書きたかったのですが、字数制限で書ききれなかったので、ここではお礼のみを書かせて頂きます。

丁寧に回答してくださっているので「わかりました!」とお答えしたいところですが、やっぱりどうしてもわかりません。

しかし解決のヒントになるような言葉を幾つも頂きましたので、咀嚼して自分のものにしてゆきたいと思います。ありがとうございました。

お礼日時:2007/12/11 11:13

>インスタンスとスレッドって、要は何が違うのでしょうか。



どちらも同じものです(ものすごく大ざっぱに言えば)。初めのうちは、それでもいいと思いますけども。

Cだって一緒ですよね。ポインタのポインタにメモリ番地など、実際に「目で見てよくわかる」なんてことは出来ないですよね。(それこそ、ビープ音が鳴ったりとか、LCDランプが一瞬光ったりとか・・・。)ただ、どのCプログラマーもみな、いろんなコードを打っていくうちに体得していくわけであって。

クラス、オブジェクト、インスタンスなんかも用は、データをどう捉えているかによって変わってくるわけであって(特に、各開発工程において)、最初のうちは同じようなもの、といった感じでいいと思います。(勉強していくうちに、次第に違いが分かってくることと思う。)

他の分野でもおんなじことです。リレーショナルDBの設計では、エンティティ[実体]って言葉を使っていますし、OracleDBでは各オブジェクト[VIEW,INDEX,SYNONYMなどなど]をスキーマ[ユーザ名]という言葉で分類していますね。(おそらく、ここのサイトの学問&教育カテでも、「理科と自然科学の違いとは?」とか「科学」と「化学」の違いとは?といった遊び半分の質問に対して、マジで熱く語っている人がいるんだろうなあ。いや、視点を変えればどうとでも論じれるだろう、って感じで。)

とまあ、雑談はこの辺にしておいて、ここからはそこそこ勉強してきた方向けの内容です。(下に行くほど、どんどんレベルが上がっていく。)

/*
Javaを始めとしたオブジェクト指向においては、この世のあらゆるモノを「オブジェクト」とみなし(但し、予約語とリテラルは識別子に使えない)、オブジェクトがどのような「属性(フィールド)」や「操作(メソッド)」を持っているのかを「クラス」を用いて分類・定義し、実際にそのオブジェクトを使用する時には「インスタンス」を生成し、「.」(ドット)を用いて関連付けをしています。(わざわざインスタンスを生成したくない時は、staticキーワードを使用する。)
*/

本来、並行処理の実現技法の一つとして使われることの多い「スレッド」という言葉もまた、Javaでは上記の考え方に基づいて使用されます。実際には、各プラットフォーム(J2ME,J2SE,J2EE)それぞれにおいて、スレッドによる実装が行われています(厳密には、「シングルスレッド」という言葉を用いますが)。

ただ、同じ「スレッド」でもマルチなものになってくると(同時に処理をさせたいとか)、すこ~しばかり実装が異なってきます。具体的には、以下の通りですね。

「マルチスレッド」用のオブジェクトの定義(J2MEとJ2SEの場合)
→java.lang.Threadクラスやjava.lang.Runnableインタフェースを利用して、runメソッドをオーバーライド(再定義)。

「マルチスレッド」用のオブジェクト使用時(J2MEとJ2SEの場合)
→該当するクラスのインスタンスを生成し、startメソッドによりスレッドの開始。

ちなみに、J2EEではHTTP通信という特殊な環境下ということもあり、そのような低レベルの処理は「サーブレットコンテナ」という別のサーバ用ソフトウェアが担当するようになっていて、各Javaプログラマーはセッション管理やカスタムタグなどそれ以外の処理に専念することが出来ます。具体的には、こんな感じ。

「マルチスレッド」用のオブジェクトの定義(J2EEの場合)
→javax.servlet.http.HttpServletクラスを継承した独自のクラスを作成し、その中でdoGetメソッド(もしくは、doPostメソッド)をオーバーライド。

「マルチスレッド」用のオブジェクト使用時(J2EEの場合)
→Webブラウザからサーブレットコンテナの動いているサーバにアクセスし、HTTPリクエストを送信。
(そしたらば、サーブレットコンテナが内部でinitメソッドやserviceメソッドなどのコールバックメソッドを実行し、いろいろな処理を行った後にHTTPレスポンスを返します。)

参考URL:http://sdc.sun.co.jp/java/docs/j2ee/sdk_1.3/ja/t …

この回答への補足

回答ありがとうございます。

(恐れながら)書かれていること全部わかります。
私の場合、理論の他、コードを書きつつの質問投稿してますから、choconamacreamさんが書かれているタイプの説明は、それはそれで理解できます。
※ちなみにDBに関することも存じています。

....しかし、スレッドというものの実体のイメージが掴めない(浮かばない)のです。

スレッド起動と言っても、要はインスタンスメソッドであるrun()の中に書かれているコードが動くわけですから、スレッドとか言ってるけど、やっぱインスタンスなんじゃないの?
と思ってしまうのです。

補足日時:2007/12/10 11:34
    • good
    • 0

メモリの抽象イメージは持っているけどCPUの抽象イメージは持ってないというところでしょうかね。


ANo.3さんの例えは良い感じですが、理解できたでしょうか。

Threadクラスはスレッドを操作するための機能を実装したクラスであってスレッド自体ではないので、Threadクラスのインスタンスとスレッド自体を混同してはいけません。
実際はThread#startメソッドの中でスレッドを起動しています。だからstartを呼び出すとスレッドが走り始めるのです。

Javaは(というかほとんどのプログラミング言語は)、オブジェクトを言語自体の機能として扱っているがスレッドを言語自体の機能としては扱えてないですから理解しにくいのも仕方ないかも。
通常スレッドは言語の機能でなくOSかライブラリかで実装する機能ですね。Javaの実装でもOSカーネルのスレッドを使うか、JavaVMと標準ライブラリの中でスレッド切り替えなどの機能を実装することで実現しています。

マルチタスクOSの内部実装を知っているとスレッドも理解しやすいのですけど、組込をやっていたならITRONの中身とか見てないですか。

この回答への補足

No.2さんも書かれていましたが、Threadクラスはスレッドを操作するための機能を実装したクラスであると...
だからThreadクラスからインスタンスを生成しても、それはあくまでインスタンスであり、スレッドではないと.....
実際はThread#startメソッドの中でスレッドを起動しています。
ここまではよーく理解できます(してると思います ^^;)

>だからstartを呼び出すとスレッドが走り始めるのです。
ここです! ここで混乱するんです!
今の今まで「これはあくまでインスタンスだぞ。スレッドじゃないぞ」と言っていたのに、そのインスタンスのstart()でいきなりスレッド登場。
そのスレッドはどこからやってくるのですか?
その、走り始めたスレッドって、要は実体は何? というのが疑問なんです。
※PecoPlusさんは、たとえ話で「読者」と表現されましたが...でもよく考えると、一つのインスタンスから複数の読者ってどうやって作るんだろう...

スレッドはインスタンスのコピーじゃないんですよね?
スレッドはフィールドやメソッドを持ってないんですよね?

もっと言うと、スレッドはコードなんですか? それともCPU時間なんですか? それとも他の何かなのでしょうか?

>マルチタスクOSの内部実装を知っているとスレッドも理解しやすいのですけど、組込をやっていたならITRONの中身とか見てないですか。
見たことないです。
暇なときにトライしたことはありますが、何が何だか、というよりどこの場所(機能)のソースを読んでいるのかすらわかりませんでした。 ..._| ̄|○

※基本的に、タスク制御の原理的な部分はできあがったところでプロジェクトに参入するし、担当を任されたスレッドの中をいじるケースばかりでしたので、
 作業的にはシングルタスクの仕事で、せいぜいが共有リソースの排他制御とか、そのくらいの仕事しか、組み込み的にはしていません。

補足日時:2007/12/10 11:25
    • good
    • 0

 こんばんは。


 よくある「オブジェクトとスレッドがごっちゃ」なってしまった状態ですね。

 例え話をするのは、よくないのでしょうが、あえて例えます。

 新聞紙を思い浮かべてください。
 新聞紙は、「紙」というメモリの上に「記事」を言うデータが記録されています。
 この記事がインスタンスであり、メソッドですね。
 では、スレッドは何かというと、「読者」です。
 読者は今読んでいるところを指でなぞりながら、読んでいるとします。
 これがシングルスレッドの状態。
 マルチスレッドでは、一枚の新聞紙を複数の読者が読んでいる状態ですね。
 なぞっている指は複数に増え、別の場所を同時に(または、偶然同じ場所を)移動していきます。

 では、「記事」と「読者」の関係はイコールでしょうか?ニアイコールでしょうか?
 そうではなく、全く違う概念の何かですね。
 インスタンスとスレッドもそうです。
 お互い関係はあるが、全く違う概念の何かです。

>とした段階では aaa はインスタンスなんですよね。でも、
> aaa.start();
>とした瞬間に、今度はスレッドとして(?)動き出しますよね?

 クラスAaaは、Threadを継承させていますが、これは間違いでもなく、別に悪くもないのですが、この手の混乱の原因になりやすいです。
 インスタンスとスレッドの関係を一番わかりやすく、書き直すとすれば、

class Aaa implements Runnable {
  (略)
  public void run() {(略)}
}

Aaa aaa = new Aaa();
Thread thread = new Thread(aaa);
thread.start();

 こうでしょう。

 クラスAaaは、スレッドではありません。
 新たに作られた読者(スレッド)によって読まれる記事(インスタンス)の一つでしかありません。
 クラスAaaのインスタンスaaaが新しいスレッドとくっついているような錯覚を起こしてしまいがちですが、これは、間違いです。
 記事と読者はくっついたりしません。
 Aaaは、新しいスレッドが読み始める導入部分であるrunメソッドを持っていると言うだけにすぎません。
 あとは、スレッドがどこに飛んでいくかは、プログラマー次第であり、aaaとスレッドが強い関連性を持っているとは限りません。
 それは、プログラマーの設計によって変わってきます。

この回答への補足

回答ありがとうございます。

新聞紙と読者のたとえ話、結構よくわかりました。ピクン、とくるものがありました。 何度もよーく読み返してみます。

ところでこの implements ですが、確かに最初に読んだ本(やさ○い Java)に載っていたのですが、
Javaは多重継承ができないから、それをやるための一手段としてちょっと紹介されていただけでした。

PecoPlusさんが書かれたのとそっくりなコードも書かれていましたが、あくまでスレッド起動は Thread から継承するのがキホンで、
implementsだと Thread thread = new Thread(aaa); というような「一手間」がかかりますよ云々..みたいな書き方だったんですけどねえ。
(ちなみに私が見た限り、他の入門書も implements になるととたんにページ数が減って、オマケ的な書き方しかされていませんでした)

...話がソレましたが、PecoPlusさんが書いてくださったコード(class Aaa implements ~thread.start();まで)は、形式的な意味合いは理解しますが、正直、何でそういうコードになるのか、もっと言うと、implementsを使わずに、Threadから単純に継承したクラスと何が違うのかが、わからないです。
※あちこちのサイトでいろいろ読んだ上で「わからない」と言ってるんですけどね。

>クラスAaaのインスタンスaaaが新しいスレッドとくっついているような錯覚を起こしてしまいがちですが、これは、間違いです。
これがわからないですねえ...本気でわからないです。 くっついてるんじゃないんですか?
いかにもインスタンスからスレッドが生まれました、って感じのコードですし (^_^;;)
(さっきの例えでいえば、記事と読者はくっついたりしないということは、頭の一方で理解しつつ...)

くっついてるというより、一対一じゃないんですか?
実際、PecoPlusさんが書いてくださったコード(class Aaa implements ~thread.start();まで)で、一つのインスタンスと一つのスレッドが生まれて(?)いますが、
その同じインスタンスからもう一つスレッドを作ることはできない(具体的には、thread.start();をもう一行書く)ですよね?
※実際やったら例外エラーになりました。
てことは一対一なんじゃあ.........うーん、せっかくお答え頂きましたが、たとえ話の箇所以外は理解できませんでした。

補足日時:2007/12/10 11:01
    • good
    • 0

java.lang.Thread が (OS レベルなどで言う) スレッドとイコールと考えていませんか?


java.lang.Thread クラスのインスタンスはスレッドを動作させるための情報とかを持った構造体に過ぎないと考えた方がよいのではないですか? インスタンスを生成すると、スレッドを動かすための準備が整い、java.lang.Thread#start() をコールしてはじめて (OS レベルなどで言う) スレッドが動作します。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

>インスタンスを生成すると、スレッドを動かすための準備が整い、
うーん、そうですよね。
現在、そういう理解というか考え方をしています。

で、それじゃstart()で動き出したスレッド(の実体)ってナニモノなの?インスタンスと何が違うの?というのが私の根元的な疑問なのです。
(もしかして私はOSレベルのスレッドすら意味があまり分かってないのかなあ...)

本を読むと、よく、「あくまでこれはインスタンスに於ける話です。スレッドではありませんので混同しないように」なんて書いてあって、そこがわからないのです。

お礼日時:2007/12/10 10:13

端的にいうと、インスタンスはメモリ領域の抽象化でスレッドはCPUの抽象化です。


ただこれだけでは分からないでしょうね(^-^;)。

インスタンスはオブジェクトの実体です。
クラスはオブジェクトの定義で、Cで言えば構造体の定義とその構造体を操作する関数(メソッド)たちを一緒にしたようなものです。そしてインスタンスはその構造体の変数だと思えば良いです。
# 厳密にはJavaのオブジェクト変数は参照なのでCでいうとポインタにメモリを割り当てて使っているような感じですけど

これに対してスレッドは実行の単位です。組込系の用語ではタスクと同等です。スレッドはあるインスタンスのメソッドから別のインスタンスのメソッドを呼び出すことによって、ある意味インスタンス間を渡り歩いて一つの動作を作り上げます。マルチスレッドではこのようなスレッドが複数同時に動作して互いに干渉しながらプログラム全体の動作を作り上げます。
JavaではThreadクラスがありますが、これはスレッドの出発点となるメソッドを持ち、スレッドの状態などにアクセスするためのクラスで、スレッド自体とは異なります。

この回答への補足

回答ありがとうございます。

>...インスタンスはメモリ領域の抽象化でスレッドはCPUの抽象化です。
前者はよくわかります。しかし後者は...実行単位の抽象化とでも言ったらいいのでしょうか。

>インスタンスはオブジェクトの実体です。
>クラスはオブジェクトの定義で、Cで言えば構造体の定義とその構造体を操作する関数(メソッド)たちを一緒にしたようなものです。そしてインスタンスはその構造体の変数だと思えば良いです。
この辺りも理解できます。まさにそうですよね。 自分はC++も仕事で一度やったのでイメージできます。

>これに対してスレッドは実行の単位です。組込系の用語ではタスクと同等です。
>スレッドはあるインスタンスのメソッドから別のインスタンスのメソッドを呼び出すことによって、ある意味インスタンス間を渡り歩いて一つの動作を作り上げます。
>マルチスレッドではこのようなスレッドが複数同時に動作して互いに干渉しながらプログラム全体の動作を作り上げます。
この辺りのこともわかります(わかるつもりです)。今、頷きながら読んでいます。
実際のプログラムを読むと、まさにそういう感じですからね。

ただ、上記のように説明頂ければそれはそれでわかる(つもり)ですが、実体のイメージが湧かないのです。
インスタンスは、要するにメモリ上に確保された「変数と関数込みのオブジェクト」というイメージが湧くので理解しやすい。
しかしスレッドは? その実体はなんなのか? CPUの(シェアされた)時間? それにしちゃあ Threadていうクラスがあるじゃん....うーむ.....

例えば、
 class Aaa extends Thread {
  (略)
  public void run() { (略) }
 }
とやって、
 Aaa aaa = new Aaa();
とした段階では aaa はインスタンスなんですよね。でも、
 aaa.start();
とした瞬間に、今度はスレッドとして(?)動き出しますよね? この辺がわからないのです。
スレッドって、同じインスタンスからコピーされた、非同期に動くインスタンスのような感じもするし...うーむ..

補足日時:2007/12/07 10:08
    • good
    • 0

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