• ベストアンサー

310-035の参考書の中にあるThreadとRunnableの説明

310-035の試験を1か月程勉強中です。スレッドについて頭がゴチャゴチャになってしまいました。 スレッドのインスタンス化ですが、 Threadを継承した場合は単純に Thread t = new Thread() でよいが、 Runnableを実装した場合は、 1行目// MyRunnable r = new MyRunnable(); 2行目// Thread t = new Thread(r) とする。とあります。 説明として、「Runnableの場合はスレッド自身のrun()メソッドではなく独自に定義したrun()メソッドを使用するようにするため」とあるのですが、何をいわんとしてるのか、この説明の意味がわからないのです。。 「スレッド自身のrun()メソッド」「独自に定義したrun()メソッド」って何のことを指してるんでしょうか。 「Threadを継承した場合」はオーバーライドしているので「スレッド自身のrun()メソッド」を見てるってことでしょうか。?? それと、どうしてRunnableの場合は、Threadをextendしてないのに急に2行目のところでThread が現われるんでしょうか。 アドバイスを頂けると助かります。宜しくお願いします。

  • Java
  • 回答数4
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • bnosuke-x
  • ベストアンサー率39% (43/110)
回答No.4

>java.lang.ThreadのインスタンスというのはだいたいThreadを拡張(extends Thread)しないとできないんじゃないか・・と思い混乱しています。 そんなことはありません。 extendsしていないjava.lang.Threadのインスタンスは取得できます。 >Runnableの実装の場合について、(以下略) >これってどうしてなんでしょうか。 逆に聞くと、何で素のjava.lang.Threadのインスタンスが作れないんですか? と言うことになります。 落ち着いて考えてください。 runの中身を「Threadの子クラス」に書くか、「Runnableを実装したクラス」に書くか、です。 Threadをextendsするのは「Threadの子クラス」を使うやり方だけです。 「Runnableを実装したクラス」を使う場合はThreadには手をつけません。 --------------------------- 2つのやり方があるのです。 ●Threadの子クラスを使う Threadを継承、run()をオーバーライドするのは、Threadの子クラスのインスタンス単独でスレッドを走らせるときのみです。 このときは実行する処理を「Threadの子クラスのrun()」に書きます。 public myThread extends java.lang.Thread { public void run() { /*別スレッドでやらせたい処理*/ } } myThread th = new myThread(); th.start(); ●Runnableを実装したクラスを使う 素のThreadクラスとRunnableインターフェイスを実装したクラスのインスタンスをでスレッドを走らせるときは、Threadの継承、run()をオーバーライドする必要はありません。 このときは実行する処理を「Runnableインターフェイスを実装したクラスのrun()」に書きます。 public anyRunnable Implements java.lang.Runnable { public void run() { /*別スレッドでやらせたい処理*/ } } anyRunnable anyRun = new anyRunnable (); Thread th = new Thread(anyRun); th.start(); Threadの継承は必須ではありません。

recycle_rocket
質問者

お礼

ご回答ありがとうございました。 extendsしていないjava.lang.Threadのインスタンスは取得できます。・・ という部分でようやく理解できるようになりました。 これまで分ったような分らないようなというかんじで暗記的に進めていましたが、これでスレッドの部分がスッキリしました。本当にお世話になりました、ありがとうございました。

その他の回答 (3)

  • ngsvx
  • ベストアンサー率49% (157/315)
回答No.3

単純な話です。 Threadオブジェクトは、コンストラクタにRunnableオブジェクトが指定されたときは、そのRunnableオブジェクトのrunメソッドを実行し、 コンストラクタに何も渡されなければ自分の(Threadオブジェクトの)runメソッド(オーバーライドされたものを含む)を実行する。 ということです。

recycle_rocket
質問者

お礼

ご回答ありがとうございました。なるほど・・コンストラクタに何も渡されなければThreadオブジェクトのrunメソッドをみてるんですね。 ありがとうございました。

  • bnosuke-x
  • ベストアンサー率39% (43/110)
回答No.2

スレッドを実行するときには「駆動するもの」と「駆動されるもの」の2つが必要です。 「車」と「荷物」のようなものです。 荷物を運ぶときは、 1)車の荷台に直接載せる方法と、 2)荷物を別の「荷台だけの車(トレーラー)」に載せて、車に牽かせる方法があります。 1)の方法は、荷物を車の荷台に載せて自分だけで走ります。 ですが、この車は走ることが目的のものなので、あまり荷物は載せたくないのが正直なところです。 2)の方法は、荷物をトレーラーに載せて、車とつなげて運びます。 トレーラーは荷物を載せるのが目的のものなので、存分に荷物を載せられます。 ポイントは、「どちらにしても車は必要」だと言うことです。 上の車と荷物の話をJavaのスレッドの話に置き換えると下のようになります。 車:Threadクラス 荷物:runメソッドの中身 荷台:runメソッド 荷台だけの車(トレーラー):Runnableインターフェイスを実装したクラス 荷物を載せる:runメソッドの中身を書く トレーラーと車をつなげる:Runnableインターフェイスを実装したクラスのインスタンスに、Threadクラスのインスタンスを割り当てる そして、 車の荷台に載せる方法:Threadのrunメソッドをオーバーライドする方法 トレーラーに乗せてそれを牽く方法:Runnableインターフェイスを実装したクラスのrunメソッドを使う方法 です。 どちらの方法でも「runメソッドをThreadクラスのインスタンスが駆動してゆく」という点では変わりません。 その証拠にThreadクラス自身もRunnableインターフェイスを実装しています。 以上をふまえて、ご質問にお答えします。 >「スレッド自身のrun()メソッド」 Threadクラスを継承して作ったクラスのrunメソッド >「独自に定義したrun()メソッド」 Runnableインターフェイスを実装したクラスのrunメソッド です。 >それと、どうしてRunnableの場合は、Threadをextendしてないのに急に2行目のところでThread が現われるんでしょうか。 Runnableインターフェイスを使う場合にThreadクラスが登場するのは、Runnableインターフェイスを実装したクラスのrunメソッドをThreadクラスのインスタンスが呼び出して処理が進むからです。 ところで、sunのドキュメントを読むと、 「Thread クラスのメソッドのうち、run() だけをオーバーライドして使用する場合は、Runnable インタフェースを使用してください。これは、クラスの基本的な動作を修正または拡張するのでない限り、そのクラスをサブクラス化することは好ましくないため、重要です。」 とあります。 Threadを継承するときはThreadの亜種を作る場合にするのが望ましく、スレッドで別処理をさせたいだけなら、そのためのクラスを別に作りましょう、と言うことだと思います。 たいていの書籍は、インターフェイスの説明が必要ないので、Threadの継承で説明が始まっていると思いますが、クラスの設計上はあまりよくないと思うので、小さいものでもRunnableインターフェイスを使ったやり方の方がいいと思います。

recycle_rocket
質問者

お礼

ご回答ありがとうございます。 しくみ等納得できました。分りやすいご説明ありがとうございました。 ここでまた分らない点があります。 Runnableの実装にしてもjava.lang.Threadの拡張(extends Thread)にしてもjava.lang.Threadのインスタンスというのを呼び出そうとしています。 java.lang.ThreadのインスタンスというのはだいたいThreadを拡張(extends Thread)しないとできないんじゃないか・・と思い混乱しています。 Runnableの実装の場合について、Threadを拡張(extends Thread)してないのに、急にThread t = new Thread(r) というかんじでjava.lang.Threadのインスタンスを明示的に取得できてますよね…。 これってどうしてなんでしょうか。 ご回答に対する御質問となってしまいすみません。 もしお時間があれば宜しくお願いします。

  • PED02744
  • ベストアンサー率40% (157/390)
回答No.1

単一継承とインタフェースの話だと思われます。 Javaは多重継承を許さないので、こんなことになってます。 詳細は、ここを http://msugai.fc2web.com/java/thread/create.html

recycle_rocket
質問者

お礼

ご回答ありがとうございます。参考urlありがとうございました。 Javaは多重継承を許さない。。たしかにそうでした。 ありがとうございました。

関連するQ&A

  • コンパイルエラー(Threadオブジェクト化)

    Runnableを継承したNormalClassをThreadとしてオブジェクト化しようとしているのですが、コンパイルエラーが出現して困っています。どうすればいいでしょうか? 下記エラー参照 Main.java:1: NormalClass は abstract でなく、java.lang.Runnable 内の abstract メソッド run() をオーバーライドしません。 下記ソース class NormalClass implements Runnable{ } class Main extends Thread{ public static void main(String args[]){ test = new Thread(new NormalClass()); } }

    • ベストアンサー
    • Java
  • Runnableのインスタンス化について

    下記のコードについてです。 Runnableがインスタンス化されていますが、 どうしてそれが可能なのかが分かりません。 分からない点は 1.Runnableはインタフェースであるから、本来、直接インスタンス化は不可能であるはず。 2.しかし、Runnableはクラスライブラリjava.langパッケージに含まれている。 だからインスタンス化は可能なのかもしれない。 3.あるいは、下記のコードではメソッド内の無名クラスであるから、「new Runnable(){」の 部分でスーパークラスとしてのRunnableを継承したサブクラスを生成しているのかもしれない。 アドバイスをよろしくお願い致します。 public class Main{ public static void main(String[]args){ Runnable task = new Runnable(){ public void run(){ System.out.println("run"); } }; Thread thread = new Thread(task){ public synchronized void start(){ System.out.println("start"); } }; thread.start(); } }

    • ベストアンサー
    • Java
  • synchronized を施しているのに・・・

    java初心者です。宜しくお願い致します。 あるスレッドがsynchronizedのメソッドを実行すると、そのメソッドの仕事は連続したひとかたまりの処理として実行される、と習いました。 なるほど、と思ったのですが、 自分で次のようなコードを書いてみると、そのようになりません。 ならない時もある、と言ったほうが正確でしょう。 具体的には、 0 1 別の処理 2 や、 0 別の処理 1 2 となったりします。 ご面倒でしょうが、コードを書きますので、解析して解りやすく教えて頂けると嬉しく思います。 class MyRunnable10 implements Runnable{ public synchronized void run(){ for(int i=0 ; i<3 ; i++){ System.out.print(i + " "); } } } class MyRunnable20 implements Runnable{ public void run(){ System.out.print("別な処理"); } } public class Exec2 { public static void main(String[] args) { Runnable m = new MyRunnable10(); Runnable m2 = new MyRunnable20(); Thread t1 = new Thread(m,"A"); Thread t2 = new Thread(m2); t1.start(); t2.start(); } }

    • ベストアンサー
    • Java
  • Java言語のインタフェースについて

    Java言語を学習している者です。 インターフェースについて理解できずに困っております。 ここでは、Runnableインターフェースを例にとります。 (1)正しいコード public class ThreadTest implements Runnable { public static void main (String args[]) { ThreadTest ins = new ThreadTest(); Thread th = new Thread(ins); th.start(); for(int i = 0; i < 10; i++) { System.out.println("main : " + i); } } public void run() { for(int i = 0; i < 10; i++) { System.out.println("run : " + i); } } } (1)のコードは正常に動きます。 (2)間違ったコード (implements Runnableを記述しなかった場合) public class ThreadTest{ public static void main (String args[]) { ThreadTest ins = new ThreadTest(); Thread th = new Thread(ins); th.start(); for(int i = 0; i < 10; i++) { System.out.println("main : " + i); } } public void run() { for(int i = 0; i < 10; i++) { System.out.println("run : " + i); } } } (2)のコードでは、 Thread th = new Thread(ins); で、 コンストラクタ―Thread(ThreadTest)は未定義です。 とエラーが出てしまいます。 確かに未定義なのですが、(1)でも定義していないように思えます。 Runnableインターフェースの働きのお陰だと言うことはわかるのですが、どういった働きによるものなのかがわかりません。 インターフェースのについて、 ・インターフェースのフィールドは必ず定数。 ・インターフェースのメソッドは必ず抽象メソッド。 ・インターフェースはインスタンスを作ることが出来ない。 ・抽象メソッドは必ず実装しなければならない。 は理解しているつもりです。 今回の質問をするに当たって、 RunnableのAPI http://java.sun.com/javase/ja/6/docs/ja/api/java/lang/Runnable.html を見たのですが、それでも理由が分からないので質問致します。 もし宜しかったら、APIの見方についてもコメントして頂けるとありがたいです。 宜しくお願いします。

    • ベストアンサー
    • Java
  • ThreadとRunnableのlogへの表示差異

    マルチスレッドでsleep()の時間を指定して動かすのを前提で、 Threadを継承した時は、時間通りに(リアルタイムで) eclipseのコンソールへ表示されるのですが、 Runnableをインプリメントしての動作では、 eclipseのコンソールに一瞬で表示されるのは何故でしょうか? public class MultiThread3 implements Runnable{ int time; MultiThread3(int time) { this.time = time; } public void run() { for(int i=0; i<5; i++) System.out.println("No."+i+":"+Thread.currentThread().getName()); try{ Thread.sleep(time); }catch (InterruptedException e) {} } } class MultiThreadTest3{ public static void main(String[] args) { MultiThread3 a = new MultiThread3(500); MultiThread3 b = new MultiThread3(700); MultiThread3 c = new MultiThread3(1100); Thread ta = new Thread(a); Thread tb = new Thread(b); Thread tc = new Thread(c); ta.setName("A"); tb.setName("\tB"); tc.setName("\t\tC"); ta.start(); tb.start(); tc.start(); } }

    • ベストアンサー
    • Java
  • Threadの終了

    http://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ja/api/index.html を見ると,スレッドの止め方が書いてありますが, これは,スレッドblinker内でループが回っていて初めてうまく行く, と(間違ってるかもしれませんが)理解しています. では下記のように,Thread2でループが回っていない場合は (*)の位置でThread2を止めるにはどうすればいいのか, 教えてくださる方はいらっしゃいませんでしょうか. (**)のClassAではSWTでGUIを表示させていて, それをThread1から閉じるというのが目的です. GUIを閉じない限りその先には進まないので, ループを回しThread2のrun()内で待機させることが出来なくて. public class Thread1 { Thread1(){ Thread2 t2 = new Thread2(); t2.start(); try { Thread.sleep(5000); } catch (InterruptedException e) { } (*)ここでThread2を終了させたい. } public static void main(String args[]){ new Thread1(); } class Thread2 extends Thread { public void run() { new ClassA(); ・・・(**) } } }

    • ベストアンサー
    • Java
  • ~クラスのメソッドと言った場合継承したものを含むか

    お世話になります。 OJC-Pの勉強中、以下の模試問題が出題されました。 ------------------- Threadクラスのメソッドとして正しいものを全て選びなさい wait() notify() run() start() ------------------- 解答はrun()、start()の2つだったのですが、 この場合、Objectクラスから継承したメソッドは Threadクラスのメソッドとは言わないのかを疑問に感じました。 (外部クラスから見た場合、 継承したメソッドもThreadクラスで新しく定義されたメソッドも区別は ないのでは、と考えたためです。) 問題文の表現に不備があるのでしょうか、 それともやはり 「~クラスのメソッド」と言った場合、継承したものは含まないとするのが 一般的な解釈なのでしょうか。 また、後者の場合、それはどうしてなのか理由なども添えていただけると 嬉しいです。 よろしくおねがいいたします。

    • ベストアンサー
    • Java
  • 別クラスのスレッドによるpaint()が上手くいきません!!

    たびたびすみません、、、今度は別のクラスに記述したpaint()をメインでスレッド起動しても描写されません…オーバーライドか何かしなければいけないらしい情報を探し当てた気がするのですが、いまいちよくわかりません。。どうすればいいのでしょうか? 下に自分で作ってみたソースの抜粋を書きます。 import java.awt.*; import java.awt.event.*; class test extends Frame { subclass sc = new subclass(); Thread th=new Thread(sc); public static void main(String args[]) { test t=new test(); } public test() { setTitle("Test"); setSize(300,200); setVisible(true); th.start(); //閉じる addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); } } class subclass extends Frame implements Runnable { int i; public void run() { for(i=0;i<100;i++) { repaint(); } try { Thread.sleep(1000); } catch(InterruptedException e){} } public void paint(Graphics g) { g.drawOval(i,i,50,50); } } (EOS) どうか教えていただける方、お願いします!!

  • インターフェイスの使い方がわかりません(初心者です)

    Javaを始めたばかりの初心者です。 「やさしいJava」を買って一通り学んだのですが、 インターフェイスの使い方がよくわからず、困っています。 インターフェイスを実装することでインターフェイスが持つメソッドがすべて定義されてることが保障される、 というのはわかるんですが、そのことがどうして有用なのでしょう? また、具体的にはスレッドを扱うときにRunnableインターフェイスを実装する理由がわかりません。 Threadクラスのオブジェクトを作成するときに、 Runnableを実装したクラスのオブジェクトの変数を 引数にしないといけないんですよね? このとき、Runnableインターフェイスが 「runメソッドが定義されていなければならない」 とだけいうものだったとしたら、 Runnableを実装してなくてもrunメソッドさえ定義してあれば 実行できそうな気がするんですが・・・

    • ベストアンサー
    • Java
  • Javaのスレッドに関して質問です

    Assistantクラスを使い待機状態と再開を確認できるプログラムの作成 loafとrestartメソッドを設ける workメソッドが呼ばれる度loafを呼び出す Managerクラスを定義 checkメソッドを設け、Assistantをcheckし続ける loaf状態ならrestartさせる (Managerクラスはデーモンスレッド) ということなんですが、いまいちうまくいきません さぼっても復帰してくれません public class Assistant implements Runnable { private String name; private Chore c; public Assistant(String name, Chore c) { this.name = name; this.c = c; } public void run() { work(); } public void work() { while (true) { synchronized (c) { if (c.doEnd()) break; System.out.println(name + " : " + c.digest()); loaf(); } } } public synchronized void loaf() { try { c.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void restart() { c.notify(); } } public class Chore { private String name; private int step; private int id; public Chore(String name) { this.name = name; this.step = this.name.length(); this.id = 0; } public synchronized String digest() { String message = "" + id + name.charAt(id); try { Thread.sleep(500); } catch (InterruptedException ie) { } id++; return message; } public synchronized boolean doEnd() { return id >= step; } } public class Manager extends Thread { private String name; private Assistant a; public Manager(String name) { this.name = name; } public void run() { check(); } public void check() { a.restart(); } } public class Test { public static void main(String[] args) { Chore[] ch = { new Chore("掃除"), new Chore("プリント印刷"), new Chore("出欠データ入力") }; Assistant[] a = { new Assistant("あ", ch[0]), new Assistant("\tい", ch[1]), new Assistant("\t\tう", ch[2] }; Thread[] t = new Thread[a.length]; for (int i = 0; i < t.length; i++) { t[i] = new Thread(a[i]); } for (int i = 0; i < t.length; i++) { t[i].start(); } Manager m = new Manager("監査"); m.setDaemon(true); m.start(); for (int i = 0; i < t.length; i++) { try { t[i].join(); } catch( InterruptedException ie ) { } } }

    • ベストアンサー
    • Java

専門家に質問してみよう