Presentation is loading. Please wait.

Presentation is loading. Please wait.

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

Similar presentations


Presentation on theme: "マルチスレッド処理 (II) Multithreading"— Presentation transcript:

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

2 スレッドの例 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

3 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の同期することができます。

4 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)を使うと問題を解く。

5 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;

6 並行スレッドが共有巡回バッファ(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()

7 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

8 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

9 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

10 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

11 課題 (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;

12 課題 (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

13 課題 (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 {}


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

Similar presentations


Ads by Google