Download presentation
Presentation is loading. Please wait.
Published byFarida Budiaman Modified 約 5 年前
1
計算機プログラミングI 第12回 スレッド インターフェース 授業アンケート 計算機プログラミングI (増原) 2003年度
2
同時に複数の絵を描かせたい 配列のところで すでに実現済み 計算機プログラミングI (増原) 2003年度
3
同時に複数の絵を描かせたい プログラム 繰り返しの中で、各タートルを少しずつ動かす 円の一部を描く 星の一部を描く
for(int j = 1; j <= steps; j++){ hm[0].fd(circleLength); hm[0].rt(circleAngle); } for(int j = 1; j <= steps; j++){ hm[0].fd(circleLength); hm[0].rt(circleAngle); hm[numTurtles-1].fd(starLength); if (j % starTurnInterval == 0) hm[numTurtles-1].rt(starAngle); } for(int j = 1; j <= steps; j++){ hm[numTurtles-1].fd(starLen); if (j % starTurnInterval == 0) hm[numTurtles-1].rt(starAng); } 星の一部を描く 計算機プログラミングI (増原) 2003年度
4
同時に複数の絵を描かせたい 複雑なプログラムで絵を描く場合は? 計算機プログラミングI (増原) 2003年度
5
プログラムは・・・? 繰り返しの中で、各タートルを少しずつ動かす ↑ このやり方は、 1回の動きが単純なときしか通用しない! ↓ スレッド
独立した計算の流れ (ここではタートルを動かす操作) 計算機プログラミングI (増原) 2003年度
6
スレッドが1つの プログラムの実行 Turtle ListDemo LinkedTurtle (いままで) 計算の流れは1つ
public class Turtle{ boolean withKame = true; public static boolean withKameAll = true; public Color kameColor = Color.green; TurtlePanel f; // set by TurtlePanel double angle; // turtle current angle double x, y; // turtle current position double dx, dy; // dx = sin(angle), dy = -cos(angle) boolean penDown; // pen status (up or down) Color c = Color.black; // pen color int kameType = 0; int rx, ry; boolean rubber = false; int moveWait = 20; int rotateWait = 20; public Turtle(int x,int y, int ia) { this.x = ((double)x + 0.5); this.y = ((double)y + 0.5); setangle((double)ia *Math.PI/180.0); penDown = true; } public double kameScale = 0.4; public int kame[][] = kameFig; public int kameR[][] = kameRFig; public int kameL[][] = kameLFig; void kameDraw(Graphics g, int data[][]) { int ix = (int)x, iy = (int)y; g.setColor(kameColor); for (int i = 0; i < data.length; i++) { int px = 0, py = 0; for (int j = 0; j < data[i].length; j += 2) { int kx = data[i][j], ky = data[i][j+1]; int nx = (int)((kx*(-dy) + ky*(-dx)) * kameScale); int ny = (int)((kx*dx+ ky*(-dy)) * kameScale); if (j > 0) g.drawLine(ix + px, iy + py, ix + nx, iy + ny); px = nx; py = ny; g.setColor(c); g.fillOval(ix - 1, iy - 1, 2,2); void show(Graphics g) if (rubber) { g.drawLine(rx, ry, (int)x, (int)y); if (withKame && withKameAll) { switch ((kameType/2) % 4) { case 0: case 2: kameDraw(g, kame); break; case 1: public class ListDemo { public static void main(String[] args) { f.addButton("追加"); f.addButton("削除"); f.addButton("前進"); f.addButton("回転"); LinkedTurtle l = null; while (true) { String command = f.getPressedButton(); if (command.equals("追加")) { int x = f.getClickedX("クリックして下さい"); int y = f.getClickedY(); Turtle m = new Turtle(x,y,0); f.add(m); m.fd(0); l = new LinkedTurtle(m,l); } else if (command.equals("前進")) { l.forwardAll(10); } else if (command.equals("回転")) { Turtle.speedAll(Turtle.speedFast); l.turnAll(); Turtle.speedAll(Turtle.speedSlow); } else if (command.equals("削除")){ Turtle m = l.firstTurtle; m.kameColor = java.awt.Color.red; l = l.next; } Turtle ListDemo (いままで) 計算の流れは1つ public class LinkedTurtle extends Turtle{ public LinkedTurtle next; public LinkedTurtle(Turtle f, LinkedTurtle n) { firstTurtle = f; next = n; } public void forwardAll(int s) { fd(s); if (next != null) { next.forwardAll(s); public void turnAll() { lt((int)(Math.random()*360)); next.turnAll(); LinkedTurtle 計算機プログラミングI (増原) 2003年度
7
mのrunから処理を始める スレッドをそれぞれ作る
スレッドを使ったプログラム import java.awt.Color; public class Multi91 extends House implements Runnable{ int n, s; Multi91(int x, int y, int a, int n, int s){ super(x, y, a); this.n = n; this.s = s; } public void run(){ polygon(n,s); public static void main(String[] args){ TurtleFrame f = new TurtleFrame(); Multi91 m = new Multi91(200,200,0, 10,50); f.add(m); Multi91 m1 = new Multi91(100,200,0, 5,50); f.add(m1); m1.setColor(new Color(255,0,0)); m1.speed(5); Thread t = new Thread(m); Thread t1 = new Thread(m1); t.start(); t1.start(); System.out.println("Main メソッドは終了する."); } public class House extends Turtle { public void polygon(int n, int s){ int a = 360/n; for(int j = 0; j < n; j++){ fd(s); rt(a); } mのrunから処理を始める スレッドをそれぞれ作る スレッドの処理を 開始させる 計算機プログラミングI (増原) 2003年度
8
スレッドを使ったプログラム public class Multi91 extends House implements Runnable{
import java.awt.Color; public class Multi91 extends House implements Runnable{ int n, s; Multi91(int x, int y, int a, int n, int s){ super(x, y, a); this.n = n; this.s = s; } public void run(){ polygon(n,s); スレッド= 独立した計算の流れ 最初のスレッドは mainから始まる public static void main(String[] args){ TurtleFrame f = new TurtleFrame(); Multi91 m = new Multi91(200,200,0, 10,50); f.add(m); Multi91 m1 = new Multi91(100,200,0, 5,50); f.add(m1); m1.setColor(new Color(255,0,0)); m1.speed(5); Thread t = new Thread(m); Thread t1 = new Thread(m1); t.start(); t1.start(); System.out.println("Main メソッドは終了する."); } public class House extends Turtle { public void polygon(int n, int s){ int a = 360/n; for(int j = 0; j < n; j++){ fd(s); rt(a); } 計算機プログラミングI (増原) 2003年度
9
スレッドを使ったプログラム public class Multi91 extends House implements Runnable{
import java.awt.Color; public class Multi91 extends House implements Runnable{ int n, s; Multi91(int x, int y, int a, int n, int s){ super(x, y, a); this.n = n; this.s = s; } public void run(){ polygon(n,s); 同じメソッドを 複数のスレッドが 実行することも できる 新しいスレッドは 引数のオブジェクトの runメソッドから実行 最初のスレッドは mainから始まる public static void main(String[] args){ TurtleFrame f = new TurtleFrame(); Multi91 m = new Multi91(200,200,0, 10,50); f.add(m); Multi91 m1 = new Multi91(100,200,0, 5,50); f.add(m1); m1.setColor(new Color(255,0,0)); m1.speed(5); Thread t = new Thread(m); Thread t1 = new Thread(m1); t.start(); t1.start(); System.out.println("Main メソッドは終了する."); } public class House extends Turtle { public void polygon(int n, int s){ int a = 360/n; for(int j = 0; j < n; j++){ fd(s); rt(a); } mのrunから処理を始める スレッドを作る startは スレッドを動かし始める 計算機プログラミングI (増原) 2003年度
10
違う図形を描いてもよい public class MultiTree extends Tree implements Runnable{
int length; MultiTree(int x, int y, int a, int length){ super(x, y, a); this.length = length; } public void run(){ tree(length); }} MultiTree MultiHilbert public static void main(String[] args){ TurtleFrame f = new TurtleFrame(); MultiTree m = new MultiTree(200,200,0,100); f.add(m); MultiHilbert m1 = new MultiHilbert(100,200,0, 5,10); f.add(m1); m1.setColor(new Color(255,0,0)); m1.speed(5); Thread t = new Thread(m); Thread t1 = new Thread(m1); t.start(); t1.start(); System.out.println("Main メソッドは終了する."); } public class MultiHilbert extends Hilbert implements Runnable{ int level,length; MultiHilbert(int x, int y, int a, int level, int length){ super(x, y, a); this.max = level; this.length = length; } public void run(){ hilbert(level,length); 計算機プログラミングI (増原) 2003年度
11
全然違うことをしたってよい public class MultiTree extends Tree implements Runnable{
int length; MultiTree(int x, int y, int a, int length){ super(x, y, a); this.length = length;} public void run(){ tree(length); }} MultiTree MultiPrime public static void main(String[] args){ TurtleFrame f = new TurtleFrame(); MultiTree m = new MultiTree(200,200,0,100); f.add(m); MultiPrime m1 = new MultiPrime(10000); f.add(m1); m1.setColor(new Color(255,0,0)); m1.speed(5); Thread t = new Thread(m); Thread t1 = new Thread(m1); t.start(); t1.start(); System.out.println("Main メソッドは終了する."); } public class MultiPrime implements Runnable{ int max; MultiTree(int max){this.max = max;} public void run(){ L: for(int i=2;i<=max;i++){ for(int j=2;j<i;j++) if(i%j==0) continue L; System.out.println(i); } 計算機プログラミングI (増原) 2003年度
12
スレッドの終了を待つ 例: 木とヒルベルト曲線を 同時に繰り返し描く ただし、繰り返しは 同期する m.setLength(i*10);
public static void main(String[] args){ TurtleFrame f = new TurtleFrame(); MultiTree m = new MultiTree(200,200,0,100); f.add(m); MultiHilbert m1 = new MultiHilbert(100,200,0, 5,10); f.add(m1); for (int i = 1; i <= 10; i++) { m.setLength(i*10); m1.setLevel(i); Thread t = new Thread(m); Thread t1 = new Thread(m1); t.start(); t1.start(); t.join(); t1.join(); } System.out.println("Main メソッドは終了する."); 例: 木とヒルベルト曲線を 同時に繰り返し描く ただし、繰り返しは 同期する スレッドが 終了するのを待つ 計算機プログラミングI (増原) 2003年度
13
スレッドの難しさ 1つのデータを複数のスレッドが変更すると、 おかしなことになる
例: 1つのタートルに2つのスレッドで木を描かせる [一般] あるスレッドが状態を変更する 一連の処理をしている間は 他のスレッドに状態を参照・変更させない トランザクション OK! 4枚 下さい OK! !?!? 3枚 下さい 5枚 2枚 計算機プログラミングI (増原) 2003年度
14
練習 Multi91.java を動かしてみる タートルをもう1匹増やす 練習問題9.1
タートルの配列を作る(cf. T51.java) スレッドの配列を作る―スレッドのi番目は タートルのi番目を担当 スレッドのi番目をstart( ) ― run メソッドが i 番目を動かす (余力があれば) ― スレッドを使ってmorphing 計算機プログラミングI (増原) 2003年度
15
練習 練習9.3 練習9.4 「2つのスレッドがsyncro()を呼び出すまで待ち、揃ったら実行を再開する」
Thread91.javaをそのまま実行 手順に従う ※ “synchorized修飾子をつける” public synchronized void polygon(int s, int n) { 意味: あるスレッドがこのオブジェクトのpolygonメソッドを実行している間は、他のスレッドは同じオブジェクトのpolygon(または別のsynchorized)メソッドを実行できない 練習9.4 「2つのスレッドがsyncro()を呼び出すまで待ち、揃ったら実行を再開する」 ※ try { 文; } catch (InterruptedException e) { } ** 「文」の中で「例外」が起きた場合、その例外を無視して**以下から実行を続ける。 「例外」 ― 突発的な事態が起きたときに、処理を中断する仕組 計算機プログラミングI (増原) 2003年度
16
引数のオブジェクトの runメソッドから実行
Threadに渡すオブジェクトの型 import java.awt.Color; public class Multi91 extends House implements Runnable{ int n, s; Multi91(int x, int y, int a, int n, int s){ super(x, y, a); this.n = n; this.s = s; } public void run(){ polygon(n,s); スレッドが作られる 引数のオブジェクトの runメソッドが出発点になる 新しいスレッドは 引数のオブジェクトの runメソッドから実行 public static void main(String[] args){ TurtleFrame f = new TurtleFrame(); Multi91 m = new Multi91(200,200,0, 10,50); f.add(m); Multi91 m1 = new Multi91(100,200,0, 5,50); f.add(m1); m1.setColor(new Color(255,0,0)); m1.speed(5); Thread t = new Thread(m); Thread t1 = new Thread(m1); t.start(); t1.start(); System.out.println("Main メソッドは終了する."); } public class House extends Turtle { public void polygon(int n, int s){ int a = 360/n; for(int j = 0; j < n; j++){ fd(s); rt(a); } オブジェクトmにrunというメソッドがなければいけない Threadコンストラクタの型は? => インターフェース 計算機プログラミングI (増原) 2003年度
17
インターフェース 宣言: 「特定の名前のメソッドを 持っていること」に名前をつける メソッドの中身は無い!!! 「runメソッドを持っていることを Runnableと名付ける」 実装: インターフェースが決めたメソッドをクラスが持っている 「Multi91はRunnableを満たしている」 = 「Multi91はrunメソッドを持っている」 型としての使用: インターフェースを実装したクラスのオブジェクトはそのインターフェースの型を持つ 「Multi91オブジェクトはRunnable型として扱える」 interface Runnable { public void run(); } class Multi extends House implements Runnable{ class Thread { Thread(Runnable o) {…} … } … new Thread(new Multi91())… 計算機プログラミングI (増原) 2003年度
18
インタフェースの目的 クラスの異なるオブジェクトを同じように扱いたい場合がある
クラスの親子関係がある → 親クラスのオブジェクトとして扱える 親子関係がない → インタフェースを使う 「特定のメソッドを持っている」 ことは時として クラスの親子関係と独立 計算機プログラミングI (増原) 2003年度
19
インタフェースの目的 クラスの異なるオブジェクトを同じように扱いたい場合がある
クラスの親子関係がある → 親クラスのオブジェクトとして扱える 親子関係がない → インタフェースを使う 飛べる モノ 「特定のメソッドを持っている」 ことは時として クラスの親子関係と独立 計算機プログラミングI (増原) 2003年度
20
インタフェースの目的 クラスの異なるオブジェクトを同じように扱いたい場合がある
クラスの親子関係がある → 親クラスのオブジェクトとして扱える 親子関係がない → インタフェースを使う 飛べる 飛ぶ() 飛べる モノ implements 「特定のメソッドを持っている」 ことは時として クラスの親子関係と独立 計算機プログラミングI (増原) 2003年度
21
インターフェース (復習) クラスの継承 インターフェース
親クラスにあるメソッドを子クラスは継承 → 子クラスも同じ名前のメソッドを全て持つ → 子クラスのオブジェクトを親クラスのかわりに使える インターフェース クラスの親子関係とは別に 「同じ名前のメソッドを持っている」ことを宣言する仕組 同じ名前のメソッドを持っている → 同じように操作できる 計算機プログラミングI (増原) 2003年度
22
m・m1は全然違うクラスだが、両方ともRunnableインターフェースを持つクラスの値なので、Threadに渡してよい
インターフェースの例 public class MultiTree extends Tree implements Runnable{ int length; MultiTree(int x, int y, int a, int length){ super(x, y, a); this.length = length;} public void run(){ tree(length); }} MultiTree MultiPrime m・m1は全然違うクラスだが、両方ともRunnableインターフェースを持つクラスの値なので、Threadに渡してよい public static void main(String[] args){ TurtleFrame f = new TurtleFrame(); MultiTree m = new MultiTree(200,200,0,100); f.add(m); MultiPrime m1 = new MultiPrime(10000); f.add(m1); m1.setColor(new Color(255,0,0)); m1.speed(5); Thread t = new Thread(m); Thread t1 = new Thread(m1); t.start(); t1.start(); System.out.println("Main メソッドは終了する."); } public class MultiPrime implements Runnable{ int max; MultiTree(int max){this.max = max;} public void run(){ L: for(int i=2;i<=max;i++){ for(int j=2;j<i;j++) if(i%j==0) continue L; System.out.println(i); } 計算機プログラミングI (増原) 2003年度
23
練習 (準備) 練習8.1 Drawable.java ― インターフェースの定義 Drawableを実装するクラスの定義
T81.java ― Drawableを使うクラス もしインターフェースがなかったら どこでエラーが出るか? 練習8.1 計算機プログラミングI (増原) 2003年度
24
ACM国際大学対抗プログラミングコンテスト
(ala 数学オリンピック) 対象:学部学生3名のチーム 日程(2003年度): 9月登録締切 web 会津など プラハ 計算機プログラミングI (増原) 2003年度
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.