マルチスレッド処理 (II) Multithreading

Slides:



Advertisements
Similar presentations
独習JAVA Chapter 6 6.6 クラスの修飾子 6.7 変数の修飾子 結城 隆. 6.6 クラスの修飾 abstract インスタンス化できないクラス。1つまたは複数のサブクラスで 実装してはじめてインスタンス化できる。 final 継承されたくないことを明示する。これ以上機能拡張 / 変更でき.
Advertisements

復習ー I (General Review I) クラスとオブジェクトの概念 Concepts of class and object クラスの宣言とオブジェクトの生成 Definition of a class and creation of an object コンストラクタとメソッドのオーバーロー.
山元進.  for 文  while 文  do ~ while 文  文のネスト  break 文  continue 文.
6.4継承とメソッド 6.5継承とコンストラクタ 11月28日 時田 陽一
社会人学習講座 「Javaプログラミング概論」
アルゴリズムとデータ構造 2012年6月27日
~手続き指向からオブジェクト指向へ(Ⅰ)~
Ex7. Search for Vacuum Problem
Javaのスレッドについて 2005年7月6日 海谷 治彦.
第4回 iPhoneアプリ開発勉強会 Objective-C 基礎講座 -クラス- 鷲見政明.
プログラミング基礎I(再) 山元進.
スレッドの同期と、スレッドの使用例 スレッドの同期 Lockオブジェクト: lockオブジェクトの生成
Ex8. Search for Vacuum Problem(2)
復習ーII (General Review II)
1.Java 概要 2.簡単なアプレット 3.動画を表示するアプレット 4.アプレットの改良 5.開発環境の利用(データベース)
アルゴリズムとプログラミング (Algorithms and Programming)
JAVA.
第2回:Javaの変数と型の宣言 プログラミングII 2007年10月2日.
計算機プログラミングI 第12回 2003年1月23日(木) インターフェース スレッド 最後に お知らせ クイズ 授業アンケート
繰り返し プログラミング 第4回 繰り返し プログラミング第4回.
JAVA GUIプログラミング 第5回 ボタンとそのイベント処理.
社会人学習講座 「Javaプログラミング概論」
第2章 Eclipseと簡単なオブジェクト 指向プログラミング
第20章 Flyweight ~同じものを共有して無駄をなくす~
インタフェース プログラミング 第14回 インタフェース プログラミング第14回.
Bridge Pattern
オブジェクト指向入門.
アルゴリズムとデータ構造 2011年6月20日
CONCURRENT PROGRAMMING
~手続き指向からオブジェクト指向へ[Ⅱ]~
実行時のメモリ構造(2) Javaスタック内動作他
細かい粒度でコードの再利用を可能とするメソッド内メソッドのJava言語への導入
11.6 ランダムアクセスファイル 11.7 StreamTokenizerクラス
8.1 例外処理 8.2 catchブロックの検索 8.3 throwステートメント 8.4 例外とエラークラス 8.6 独自の例外
プログラミング言語入門 手続き型言語としてのJava
JAVA入門後期⑩ 情報処理試験例題解説.
アルゴリズムとプログラミング (Algorithms and Programming)
第9章 例外処理,パッケージ 9.1 例外処理 9.2 ガーベッジコレクション.
独習JAVA 6.8 コンストラクタの修飾子 6.9 メソッドの修飾子 6.10 ObjectクラスとClassクラス 11月28日(金)
第7回独習Javaゼミ セクション 1~4 発表者 直江 宗紀.
オブジェクト指向 プログラミング 第十三回 知能情報学部 新田直也.
第3回 2007年4月27日 応用Java (Java/XML).
第11週:super/subクラス、継承性、メソッド再定義
10-1 SAXの概要 10-2 Saxプログラミングの基礎 10-3 saxのプログラム例
プログラミング言語論 第五回 理工学部 情報システム工学科 新田直也.
7.4 intanceof 演算子 7.5~7.9パッケージ 2003/11/28 紺野憲一
Java8について 2014/03/07.
アルゴリズムとデータ構造1 2005年7月5日
アルゴリズムとデータ構造 2010年6月21日
ソフトウェア制作論 平成30年11月21日.
Ex7. Search for Vacuum Problem
pointcut に関して高い記述力を持つ アスペクト指向言語 Josh
アルゴリズムとデータ構造 2011年6月23日
計算機プログラミングI 第12回 スレッド インターフェース 授業アンケート 計算機プログラミングI (増原) 2003年度.
アルゴリズムとプログラミング (Algorithms and Programming)
オブジェクト指向 プログラミング 第六回 知能情報学部 新田直也.
プログラミング言語論 第十一回 理工学部 情報システム工学科 新田直也.
C#プログラミング実習 第3回.
計算機プログラミングI 第3回 プリミティブ値 クラスメソッド クラス変数 式と演算 変数の利用
アルゴリズムとプログラミング (Algorithms and Programming)
アルゴリズムとデータ構造1 2006年6月23日
Chapter 5 5.5 thisキーワード 5.6 インスタンス変数とインスタンスメソッド 結城 隆
オブジェクト指向言語論 第五回 知能情報学部 新田直也.
アルゴリズムとデータ構造 2012年6月25日
JAVA入門⑥ クラスとインスタンス.
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
アルゴリズムとデータ構造 2012年6月21日
Javaとは Javaとはオブジェクト指向言語でJava VM(Java仮想マシン)と呼ばれるプログラム上で動作します。
オブジェクト指向言語論 第六回 知能情報学部 新田直也.
オブジェクト指向言語論 第九回 知能情報学部 新田直也.
Presentation transcript:

マルチスレッド処理 (II) Multithreading スレッドの同期の復習 バッファを使ったスレッドの同期 Runnable インタフェース スレッドの優先度

スレッドの例 IntegerStore Producer sets i Consumer gets j (i=j) An example of multithreading: Producer/Consumer With thread synchronization IntegerStore Producer sets i Consumer gets j (i=j) オブジェクトisを生成する時、条件変数writeableがtrueです。 class Producer extends Thread { private IntegerStore pStore; public Producer( IntegerStore iS ) { pStore = iS; } public void run() { for ( int i = 0; i < 10; i++ ) { try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); } pStore.setSharedInt( i); System.out.println( "Producer set sharedInt to " + i ); } pStore.setMoreData( false ); }} class IntegerStore { private int sharedInt = -1; private boolean moreData = true; private boolean writeable = true; public synchronized void setSharedInt( int val ) { while(!writeable) { try { wait(); } catch (InterruptedException e){ System.err.println("Exception: " + e.toString()); sharedInt = val; writeable = false; notify(); public synchronized int getSharedInt() { while (writeable){ try{ catch(InterruptedException e){ writeable = true; return sharedInt; public void setMoreData( boolean b ) { moreData = b; } public boolean hasMoreData() { return moreData; } ProducerスレッドからsetSharedIntメソッドを呼び出す。 true writeable false wait shareInt=-val writeable = false notify() class Consumer extends Thread { private IntegerStore cStore; public ConsumeInteger( IntegerStore iS) { cStore = iS; } public void run() { int val; while ( cStore.hasMoreData() ) { try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } catch( InterruptedException e ) { System.err.println( e.toString() ); } val = cStore.getSharedInt(); System.out.println( "Consumer retrieved " + val ); } }} ConsumerスレッドからgetSharedIntメソッドを呼び出す。 writeableはモニタ変数と言う. 値はtrueとfalse false writeable true public class SharedStore { public static void main( String args[] ) { IntegerStore is = new IntegerStore(); Producer p = new Producer(is ); Consumeer c = new Consumer( is ); p.start(); c.start(); }} wait Producerスレッドが終わりです writeable = true notify() return ShareInt IntegerStoreに整数がもうないからConsumerスレッドが終わりです 実行結果:L74

Monitor variable writeable モニタ変数 Monitor variable writeable writeableはモニタ変数と言う.  モニタ変数writeableはboolean型で、trueとfalse値があります。 クラスIntegerStoreの同期メソッドsetSharedIntとgetSharedIntによって参照されます。 変数writeableがtrueの場合、setSharedIntメソッドは変数SharedIntに値を書き込むことができますが、getSharedIntメソッドは変数SharedIntから値を読み出すことができません。 変数writeableがfalseの場合、 getSharedIntメソッドは変数SharedIntから値を読み出すことができますが、setSharedIntメソッドは変数SharedIntに値を書き込むことができません。 生産者スレッド(Producerオブジェクト)がsetSharedIntメソッドを呼び出すと、共有バッファ(IntegerStoreオブジェクト)がロックされます。ロックが解除されるので他の同期メソッド(getSharedIntメソッド)が共有バッファにアクセスできるようになります。 消費者スレッド(Consumerオブジェクト)がgetSharedIntメソッドを呼び出すと、共有バッファ(IntegerStoreオブジェクト)がロックされます。ロックが解除されるので他の同期メソッド(setSharedIntメソッド)が共有バッファにアクセスできるようになります。 生産者スレッドが共有バッファに書き込んだ値を消費者スレッドが正確に1回だけ読み出します。 =>setSharedIntとgetSharedIntの同期することができます。

Shared value’s access by parallel threads 並行スレッドが共有値のアクセス Shared value’s access by parallel threads (i=j) IntegerStore Producer sets i Consumer gets j IntegerStoreの最大値は一つ整数です 実行結果: L73 L74 class Producer extends Thread {   ……  public void run() { for ( int count = 0; count < 10; count++ ) { try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } …… pStore.setSharedInt( count ); pStore.setMoreData( false ); class Consumer extends Thread { ……  public void run() { while ( cStore.hasMoreData() ) { try { Thread.sleep( (int) ( Math.random() * 3000 ) ); } int val = cStore.getSharedInt(); 問題: 生産者の速度 = 消費者の速度 =>   パフォーマンスが悪くなる。               (速い/遅い)       (遅い/速い)   (スレッド待っている時間が長くなるので) 解決法: 大きいバッファ(size > 1)を使うと問題を解く。

Shared buffer’s access by parallel threads 並行スレッドが共有バッファ(size > 1)のアクセス Shared buffer’s access by parallel threads 5個整数を格納することができるようなバッファを使います。 もし共有バッファには空き場所があれば、生産者は共有バッファに値を書き込むことができます。 もし共有バッファにはまだ読んでない値があれば、消費者は共有バッファから値を読み出すことができます。 読み出す時、書き込む同じ順番に、読み出します。そのことができるように、変数writeLocation(書き込み位置)とreadLocation(読み出し位置)を使います。 読み出す時、readLocation = writeLocationの場合はバッファが空っぽなので、読み出すことができないをセットします。 書き込む時、writeLocation = readLocationの場合はバッファが満杯なので、書き込むことができないをセットします。 … Producer sets i Consumer gets j (i = j) IntegerStoreの最大値はn個整数です n=5 i1 i2 i3 i4 i5 Producer sets i Consumer gets j (i = j) IntegerStoreの最大値は5個整数です i1 i2 i3 i4 i5 readLocation writeLocation if (writeLocation = readLocation) writeable = false; if (readLocation = writeLocation) readable = false;

並行スレッドが共有巡回バッファ(size > 1)のアクセスの例 Source Code 実行結果: L81 class IntegerStore { private int sharedInt[] = {-1, -1,-1, -1, -1}; private boolean moreData = true; private boolean writeable = true; private boolean readable = false; private int readLocation = 0, writeLocation = 0; public synchronized void setSharedInt( int val ) { while(!writeable) { try { System.out.println("Producer is waiting... to set " + val); wait(); } catch (InterruptedException e){ System.err.println("Exception: " + e.toString()); sharedInt[writeLocation] = val; readable = true; System.out.print("Producer writes " + val + " to index " + writeLocation); writeLocation = (writeLocation + 1) % 5; System.out.print(", writeLocation " + writeLocation + ", readLocation " + readLocation + ", "); for (int index = 0; index < sharedInt.length; index++ ) System.out.print(" " + sharedInt[index]); System.out.println(" "); if (writeLocation == readLocation) { writeable = false; System.out.println("Buffer is full"); notify(); class IntegerStore { private int sharedInt = -1; private boolean moreData = true; private boolean writeable = true; public synchronized void setSharedInt( int val ) { while(!writeable) { try { wait(); } catch (InterruptedException e){ System.err.println("Exception: " + e.toString()); sharedInt = val; writeable = false; notify(); public synchronized int getSharedInt() { while (writeable){ try{ catch(InterruptedException e){ writeable = true; return sharedInt; public void setMoreData( boolean b ) { moreData = b; } public boolean hasMoreData() { return moreData; } true writeable false wait shareInt[writeLocation]=-val reaadable = true writeLocation = (writeLocation+1)%5 false writeLocation =readLocation true writeable = false notify()

Source Code (continue …) 並行スレッドが共有巡回バッファ(size > 1)のアクセスの例 Source Code (continue …) public synchronized int getSharedInt() { int val; while (!readable){ try{ System.out.println("Consumer is waiting... to get " ); wait(); } catch(InterruptedException e){ System.err.println("Exception: " + e.toString()); writeable = true; val = sharedInt[readLocation]; System.out.print("Consumer reads " + val + " from index " + readLocation); readLocation = (readLocation + 1)%5; System.out.print(", writeLocation " + writeLocation + ", readLocation " + readLocation + ", "); for (int index = 0; index < sharedInt.length; index++ ) System.out.print(" " + sharedInt[index]); System.out.println(" "); if (readLocation == writeLocation) { readable = false; System.out.println("Buffer is empty"); notify(); return val; public void setMoreData( boolean b ) { moreData = b; } public boolean hasMoreData() if (moreData == false && readLocation == writeLocation) return false; else return true; } class IntegerStore { private int sharedInt = -1; private boolean moreData = true; private boolean writeable = true; public synchronized void setSharedInt( int val ) { while(!writeable) { try { wait(); } catch (InterruptedException e){ System.err.println("Exception: " + e.toString()); sharedInt = val; writeable = false; notify(); public synchronized int getSharedInt() { while (writeable){ try{ catch(InterruptedException e){ writeable = true; return sharedInt; public void setMoreData( boolean b ) { moreData = b; } public boolean hasMoreData() { return moreData; } true readable false wait shareInt[writeLocation]=-val writeable = true val = sharedInt[readLocation] readLocation = (readLocation+1)%5 false readLocation =writeLocation true readable = false notify() return val

Thread(Runnable r)スレッドコンストラクタを呼び出す。 Runnable interface class CountTenThread extends Thread { public void run() { for (int i = 0; i < 10; i++) { System.out.println("run:i = " + i);}} } public class ThreadTest { public static void main(String[] args) { CountTenThread ctt = new CountTenThread(); ctt.start(); System.out.println("main:i = " + i);}} 自分定義したスレッド class thread_name extends Thread {   …… public void run(){ ……} } 実行結果:L71 クラススレッドのコンストラクタ public Thread() public Thread(String threadName) public Thread(Runnable r) public Thread(Runnable r, String threadName) …… class CountTenR implements Runnable{ public void run() { for (int i = 0; i < 10; i++) { System.out.println("run:i = " + i);}} } public class RunnableTest { public static void main(String[] args) { CountTenR ctr = new CountTenR(); Thread ctt = Thread(ctr); ctt.start(); System.out.println("main:i = " + i);}} 自分定義したRunnableクラス Runnableインタフェースの使い方 Threadから導出したサブクラスの場合と同様にRunnableインタフェースを実装したクラスでもスレッドを制御するコードはrunメソッドの中に書きます。 Runnableインタフェースを実装したクラスでそレッドを生成するには、Threadコンストラクタにそのクラスのオブジェクトへの参照を渡します。 Thread(Runnable r)スレッドコンストラクタを呼び出す。 実行結果:L82

Runnableインタフェースの例 例えば、アプレットのサブクラスRandomCharactersで三つマルチスレッド処理をしています。 An example using Runnable interface 例えば、アプレットのサブクラスRandomCharactersで三つマルチスレッド処理をしています。 どうしてRunnableインタフェースをつかいますか? マルチスレッド機能を持つ新しいクラスを作るためにThreadクラスを拡張し、並行して進める仕事をするためにrunメソッドを上書きします。 では、Threadのサブクラス以外でマルチスレッド処理を行いたい時はどうすればいいですか? =>そのクラスにRunnableインタフェース を実装しなければいけません。 Appletのサブクラスの宣言 public class RandomCharacters extends Applet implements Runnable, ActionListener{ …… Thread thread1, thread2, thread3;   public void init(){……} public void start(){   thread1 = new Thread(this, “thread-1”);  thread2 = new Thread(this, “thread-2”);  thread3 = new Thread(this, “thread-3”);  thread1.start(); thread2.start(); thread3.start(); } public stop(){ thread1.stop(); thread2.stop(); thread3.stop(); } public void actionPerformed(ActionEvent e){……} public run() { …… } Runnableインタフェースの実装の宣言 Thread(Runnable r, String s)スレッドコンストラクタを呼び出す。それぞれそレッドにRunnableオブジェクトとしてこのアプレッド自身(this)を指定します。 もう一例=> ユーザが別のWebページに移った時は、アプレッドで生成したスレッドを停止させるように、stop()メソッドを呼び出す。 ソース:L83code 実行結果:L83

An example using Runnable interface スレッド優先度 An example using Runnable interface あらゆるJavaスレッドは Thread.MIN_PRIORITY(1)からThread.MAX_PRIORITY(10) までのいずれかの優先度を持っています。スレッドにはデフォルトで Thread.NORM_PRIORITY(5) の優先度が与えられます。 スレッドメソッド public final void setPriority(int newPriority); Public final void getPriority(); class PrintThread extends Thread { String name; public PrintThread(String s) { name = s; System.out.println( "Name: " + s); } public void run() { System.out.println( name + ". Priority is " + this.getPriority()); public class PriorityPrintTest { public static void main( String args[] ) { PrintThread thread1, thread2, thread3, thread4; thread1 = new PrintThread("th-1"); thread2 = new PrintThread("th-2"); thread3 = new PrintThread("th-3"); thread4 = new PrintThread("th-4"); thread1.setPriority(1); thread2.setPriority(3); thread3.setPriority(3); thread4.setPriority(10); thread1.start(); thread2.start(); thread3.start(); thread4.start(); } 実行結果:L84

課題 (Exercise) Month feeds Baby eats Mouth ヒント:L81のプログラムを参照します。 1. Mouthの最大値は4つfeedを仮定して、先週の課  題3を元tにして、巡回バッファを4つ持ったプログラ  ムに修正せよ。 2. 先週の課題1と2のプログラムを以下のように修正せよ。 value is 1 => square is 1 => cube is 1 value is 2 => square is 4 => cube is 8 …… value is 9 => square is 81 => cube is 729  (ヒント: Calculateとしてクラスを定義して、 Claculateクラスには同期メソッドsynchronized square(int value)と synchronized cube()の定義が必要です。 その二つメソッドは共有値shareValueをアクセスします。) class Calculate {     private int sharedValue; ……. public synchronized int square(int value){ … sharedValue = value; } public synchronized int cube(){…} // using shareValue public void squareEnd(boolean end){…} public boolean cubeGo(){…} Mother takes 0~100 to feed Baby takes 0~1000 to eat Month feeds Baby eats mouthの最大値は4つfeed i1 i2 i3 i4 feedLoc eatLoc Mouth ヒント:L81のプログラムを参照します。 feedメソッドの中に eatメソッドの中に if (feedLoc = eatLoc) feedable = false; if (eatLoc = feedLoc) eatable = false;

課題 (Exercise) Month feeds Baby eats Mouth 実行結果 ex81 実行結果 ex82 1. Assume that Baby’s mouth can take the maximum 4 feeds rather 1 feed in exercise problem 3 of the last week. Rewrite the program. 2. .Modify the program for exercise problem 1 and 2 of the last week so that the output is as follows: value is 1 => square is 1 => cube is 1 value is 2 => square is 4 => cube is 8 …… value is 9 => square is 81 => cube is 729 (hint: using synchronized methods square() and cube() in Calculate class) class Calculate { ……. public synchronized int square(int value){…} public synchronized int cube(){…} //share value with square() public void squareEnd(boolean end){…} public boolean cubeGo(){…} } Mother takes 0~100 to feed Baby takes 0~1000 to eat Month feeds Baby eats mouthの最大値は4つfeed i1 i2 i3 i4 feedLoc eatLoc Mouth

課題 (Exercise) Baby’s mouth Month feeds Baby eats 実行結果 ex1 実行結果 ex2 1. Define two your own thread classes that do the following work. SquareThread class: a constructor to set the thread’s name, for i = 1 ~ 9, print value i, name of the thread, square value i*i sleep 0~1000 milliseconds print name of the thread and the string “ is done!” CubeThread class: print value i, name of the thread, cube value i*i*i 2. Write a Java application program that creates a SquareThread thread and CubeThread thread and starts these two threads. 3. Suppose that a mother feeds a sequence of foods, noted by i = 0~9, to her baby as follows: 3.1 Define MotherThread class and BabyThread class that do the following work MotherThread class: a construct to set the thread’s name, for i = 0 ~ 9, print name of the thread, feeding sequence number I sleep 0~1000 milliseconds BabyThread class: eating sequence number I 3.2 Write a Java application that creates a MotherThread thread and a BabyThread thread and starts these two threads. 3.3 Define a Mouth class that includes a synchronized feed(int value) method and a synchronized eat(int value) so that actions of mother feeding and baby eating are synchronized. Baby’s mouth Month feeds Baby eats Mother takes 0~1000 to feed Baby takes 0~1000 to eat mouthの最大値は一つfeedです class Mouth{ } class MotherThread extends Thread { } class BabyThread extends Thread { } public class MotherBaby {}