ソースコードの流れについて

このQ&Aのポイント
  • ソースコードの流れを詳しく解説します
  • 表示結果が理解できない場合は、以下のソースコードの解説を参考にしてください
  • ThクラスとMain4_1_49クラスについて説明します
回答を見る
  • ベストアンサー

ソースコードの流れについて

下記ソースコードの流れを詳しく解説していただけませんか。表示結果が理解できません。 class Th extends Thread{ public void run(){ for(int i = 0; i < 2; i++)System.out.print(" "+ Main4_1_49.count + i); } } public class Main4_1_49{ static int count = 0; public static void main(String[] args){ Th[] tr = new Th[6]; for(int i = 0; i < 5; i++){ count++; tr[i] = new Th(); tr[i].setPriority(i * 2 + 1 ); tr[i].start(); } } }

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

  • ベストアンサー
回答No.1

自分が予想するに質問者はstaticの意味を理解していないのではないかと予想するのですが、いかがでしょうか。 staticで宣言したフィールドはこのプログラムが実行されてから終了するまで大域変数のように使える値になります。 (ちなみにこういう値のことをstatic変数やクラス変数と言い、インスタンス変数とは区別されます) つまり、もし同時に実行することが出来るなら、Main4_1_49.countの結果はどのThクラスのインスタンスから実行しても同じ値が表示されます。 Javaでスレッドを作るにはThreadクラスのサブクラスを作って、start()を呼ぶとスレッドを作った上でrun()メソッドが実行されるというのは理解していると思います。 このプログラムでは、iの値を5まで増やしつつ、countの値も1ずつ増やしながらスレッドの生成とプライオリティの設定、スレッドの実行をしています。自分が思うに、スレッドを実行したらその瞬間に実行されたスレッドがCPUを貰えるわけではなく、スケジューリングのタイミングまで待たされると思います。その間もmainメソッドが実行されるので、countの値が増加し、スレッドもどんどん生成・実行されます。 スケジューリングのタイミングでrunメソッドが呼ばれますが、これが参照するcountフィールドはすでにスレッドが生成された時から値が増えていますから、増えた値を表示します。そのため、現在のcountフィールドの値(例えば4など)を表示し、iの値 (0)を表示して、40という表示が出ると思います。System.out.printは裏でシステムコールを呼び、コンテキストスイッチのタイミングになるので40とSystem.out.printを実行したタイミングで今のスレッドは止まって、次のスレッドが起き、同じくcountフィールドの値4を表示、以下同じくという流れだと思います。 もし、スレッドごとにそれを作った時のiの値を表示させたいなら、例えばThクラスのコンストラクターでidを取るようにすれば良いと思います。ソースで書くとこんな感じですね。 class Th extends Thread { private final int id; public Th (int id) { this.id = id; } public void run() { for (int i = 0; i < 2; i++) { System.out.print(" " + id + i); } } } public class Main4_1_49 { public static void main(String[] args) { Th[] tr = new Th[5]; for (int i = 0; i < 5; i++) { tr[i] = new Th(i); tr[i].setPriority(i + 1); tr[i].start(); } } } こうするとcountフィールドをプログラム内で共有する代わりに各々のThクラスのインスタンスにインスタンス変数としてidを持たせているので、Threadごとに別々の値を表示するようになります。 最後に、落穂拾い的にちょっとプログラムについて指摘させてください。 1. for (int i = 0; i < 5; i++)とするなら、new Th[5]で十分だと思います。new Th[6]だと1つ無駄です。 2. setPriorityの引数のint値は1から10までです。詳しくは下記JavaDoc参照。 http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#setPriority%28int%29 http://docs.oracle.com/javase/7/docs/api/constant-values.html#java.lang.Thread.MAX_PRIORITY 3. Javaのコード規約(code conventions)ではミスにつながるので次のような{}の省略をしないようになっています。もちろん、{}の省略は許されているので文法エラーにはなりませんが。 > for(int i = 0; i < 2; i++)System.out.print(" "+ Main4_1_49.count + i); http://www.oracle.com/technetwork/java/javase/documentation/codeconventions-142311.html#449 では、頑張って。

yoshiki72002
質問者

お礼

詳しい解説ありがとうございました。大変わかりやすい解説でとても感激してます。staticの意味は「クラスで唯一の」と頭でわかっていたつもりでしたが・・・質問したソースコードでは全く理解していませんでした。参考に記載頂いたコードを実行してよくわかりました。本当にありがとうございます。

関連するQ&A

  • [javaプログラムについて] うまく動きません。

    import java.*; class Test { void main() { Th th1 = new Th("01スレッド"); Th th2 = new Th("02スレッド"); th1.start(); th2.start(); } } class Th extends Thread { void run(String pri) { for (int i=0;i<5;i++) { System.out.println(pri + " : " + i); } } } スレッドの使い方がいまいちよく分かりません。 どこが間違っているのか教えてください。 宜しくお願い致します。

    • ベストアンサー
    • 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
  • extendsの使い方

    public class ThreadSample3 { public static void main(String[] args) { ThreadA ta = new ThreadA(); ThreadB tb = new ThreadB(); ta.start(); tb.start(); } } class ThreadA extends Thread { public void run() { try { for(int i = 0; i < 10; i++) { Thread.sleep(1000); System.out.println("ThreadA"); } } catch (InterruptedException e) { } } } class ThreadB extends Thread { public void run() { try { for(int i = 0; i < 10; i++) { Thread.sleep(2000); System.out.println("ThreadB"); } } catch (InterruptedException e) { } } } これは、ThreadAとThreadBを10回ずつ表示させるプログラムなのですが、extendsは子供と親の関係に当たり、例えば親クラスボールだったら子クラスが野球ボールやゴルフボールになると習いました。 class ThreadA extends Thread{ の部分はThreadとThreadAが親子関係になっていますか? またどうして子クラスの名前と親クラスの名前はこう書かないといけないですか。 

    • ベストアンサー
    • Java
  • NoSuchMethodErrorが解決できません。

    実行時エラーNoSuchMethodErrorが出て困っています。 どこを修正すればいいのでしょうか? class A implements Runnable{ int x; int y; public void run(){ for(int i = 0;i < 100;i++){ x++; y++; System.out.println("x="+x+"y="+y); } } } class B{ public static void main(String args[]){ new Thread(new A()).start(); new Thread(new A()).start(); } }

    • ベストアンサー
    • Java
  • スレッド間の送受信のコードについて

    下記のコードは、(以前お教え頂きました)『synchronized』を使用した、スレッド間の 送受信のコードですが、その代わりに、Interruptとか、Thread.sleep()を使用した、 コードに変更してみたいと思います。 Q1)そのコードをお教え頂けないでしょうか? class T_thread { public static void main(String args[]) { new rcvInterrupt().start(); } } class genInterrupt extends Thread { private rcvInterrupt target; genInterrupt(rcvInterrupt targetx) { this.target = targetx; } public void run() { System.out.println("genInterupt start"); for (int i = 0; i < 10; i++) { while (!target.isWaited) { // rcvInterruptがsynchronizedブロックに入るまで待ち合わせ // これがないと連続してsynchronizedしてしまう可能性がある } synchronized (target) { target.notifyAll(); target.isWaited = false; System.out.println("notify"); } } } } class rcvInterrupt extends Thread { volatile boolean isWaited; public synchronized void run() { new genInterrupt(this).start(); for (int i = 0; i < 10; i++) { try { isWaited = true; wait(); System.out.println("get interrupt cnt=" + i); } catch (InterruptedException e1) { } } } } 以上

    • ベストアンサー
    • 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の同期について package rwlock; public class App1 extends Thread { static private final int REFER = 0; static private final int UPDATE = 1; static private final int[] conf1 = { REFER, REFER, REFER, UPDATE }; static private final int[] conf2 = { REFER, UPDATE, REFER, REFER }; static private MyObj0 mo = new MyObj0(); // App1 + MyObj0 int id; private int[] conf; public App1(int id, int[] conf) { this.id = id; this.conf = conf; } public void run() { long tStart = Time.current(); for (int i = 0; i < conf.length; i++) { switch(conf[i]) { case REFER: mo.refer(); break; case UPDATE: mo.update(); break; default: assert false : "internal error"; } } if (id == 1) { Time.printElapsed(tStart); } } public static void main(String[] args) { App1 th1 = new App1(1, conf1); App1 th2 = new App1(2, conf2); th1.start(); th2.start(); } } public class MyObj0 { private Object countLock = new Object(); private int count; private void enter() { synchronized(countLock) { count++; } } private void leave() { synchronized(countLock) { count--; } } public MyObj0() { count = 0; } public void refer() { enter(); Time.sleep(300); leave(); } public void update() { enter(); synchronized(countLock) { assert count == 1; } Time.sleep(500); leave(); } において、updateの実行中は、他のスレッドでもupdateもreferも実行されないが、二つのスレッドで同時にreferは実行されうるという条件を満たすにはどうしたらよいでしょうか?updateにsynchronizedをつけてみましたが、referが同時に実行されてしまいました

    • ベストアンサー
    • Java
  • javaの同期について

    javaの同期について package rwlock; public class App1 extends Thread { static private final int REFER = 0; static private final int UPDATE = 1; static private final int[] conf1 = { REFER, REFER, REFER, UPDATE }; static private final int[] conf2 = { REFER, UPDATE, REFER, REFER }; static private MyObj0 mo = new MyObj0(); // App1 + MyObj0 int id; private int[] conf; public App1(int id, int[] conf) { this.id = id; this.conf = conf; } public void run() { long tStart = Time.current(); for (int i = 0; i < conf.length; i++) { switch(conf[i]) { case REFER: mo.refer(); break; case UPDATE: mo.update(); break; default: assert false : "internal error"; } } if (id == 1) { Time.printElapsed(tStart); } } public static void main(String[] args) { App1 th1 = new App1(1, conf1); App1 th2 = new App1(2, conf2); th1.start(); th2.start(); } } public class MyObj0 { private Object countLock = new Object(); private int count; private void enter() { synchronized(countLock) { count++; } } private void leave() { synchronized(countLock) { count--; } } public MyObj0() { count = 0; } public void refer() { enter(); Time.sleep(300); leave(); } public void update() { enter(); synchronized(countLock) { assert count == 1; } Time.sleep(500); leave(); } において、updateの実行中は、他のスレッドでもupdateもreferも実行されないが、二つのスレッドで同時にreferは実行されうるという条件を満たすにはどうしたらよいでしょうか?updateにsynchronizedをつけてみましたが、referが同時に実行されてしまいました。

    • ベストアンサー
    • Java
  • Javaのサーブレットについて(マルチスレッド)

    サーブレットについて質問です。 サーブレットは1インスタンス・複数スレッドという形態で、 サーブレットコンテナにより管理されていると思います。 では、このコンテナ内では、どのように1インスタンス・複数スレッドを 実現しているのでしょうか? 以下、自分なりに考えたプログラムです。 たぶん、このようにすれば、1インスタンス・複数スレッドになるのかと思うのですが。 どなたかご教授願いますでしょうか。 よろしくお願いいたします。 【1インスタンス・複数スレッドプログラム例】 public class TestThread extends Thread { public void run() { System.out.println("TestThread.run()"); } public static void main(String[] args) { Thread tt = new TestThread(); Thread th1 = new Thread(tt); Thread th2 = new Thread(tt); th1.start(); th2.start(); } }

  • synchronizedが解りません。

    synchronized( a ) { a.add(); } ブロック文で aオブジェクトをロックしてるはずなんですが 結果を見ると出来てないようです なぜうまくいかないんでしょうか? 教えてください。 class Test extends Thread { feet a = new feet(); public static void main( String args[] ){ for( int i = 0; i < 3; i++ ){ Test b = new Test(); b.start(); } } public void run() { synchronized( a ) { a.add(); } } } class feet{ int n, m; void add(){ n++; System.out.println( n + " " + m ); try { Thread.sleep( 1000 ); }catch( InterruptedException err ){ } m++; System.out.println( n + " " + m ); } }

    • ベストアンサー
    • Java