スレッド間の送受信のコードについて

このQ&Aのポイント
  • スレッド間の送受信のコードについて、InterruptやThread.sleep()を使用したコードについて学びましょう。
  • 質問文章のコードは、synchronizedを使用してスレッド間の送受信を行っていますが、InterruptやThread.sleep()を使用したコードに変更する方法を教えてください。
  • 新たにInterruptやThread.sleep()を使用してスレッド間の送受信を行うコードを教えてください。
回答を見る
  • ベストアンサー

スレッド間の送受信のコードについて

下記のコードは、(以前お教え頂きました)『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
  • 回答数4
  • ありがとう数8

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

  • ベストアンサー
  • OKTaro-
  • ベストアンサー率50% (36/72)
回答No.4

Q2 私の環境ではそのままコピペして動作させたもので72.5μsでした genInterupt start Cyclle time[us] T1=72.5 Cyclle time[ms] T2=0.0725 End of job Q4) 私の環境は Mac OS X Yosemite Eclipse Mars Release (4.5.0) JDK 1.8.0_45 です

bakabon_X
質問者

お礼

OKTara-さま くどくど、質問して御免なさい。 ご回答有難うございます。 丁寧なご回答有難うございました。 下記のコードの20を2000に変更して、cycle_timeは42us位になりました。 (既にお送りしましたコードから、多少変更しているかもしれません。) for(int i=0; i<20; i++){ H[ptrW]=T_threadC.DATAX++; ptrW++; if(ptrW>=T_threadC.CNT){ ptrW=T_threadC.CNT-1; } }

その他の回答 (3)

  • OKTaro-
  • ベストアンサー率50% (36/72)
回答No.3

Q1)この変更コードで受信漏れは、無いものと考えて宜しいでしょうか? 現状のコードのままであればほ確実に無いと思います。 動作環境の高負荷でThread.sleepの1秒が経過してしまったとかそういうケースは考えられますが、普通にはまずないと思ってよいと思います。 Q2)rcvInterruptに於ける受信を確認を確認することなく、送信側でDATAXの値を0から   19999に順次カウントアップしまして、その都度target.interrupt()で割込みを掛ける   方法はありますでしょうか? イマイチイメージが出来ないのですが、T_threadC.transferedを使わずにとかそういう事でしょうか? Q3)コードの旨くない所があれば、ご指摘頂けますと大変有り難いです。 以上、お手数ですが宜しくお願いします。 動作としては問題ないと思います。 ただ不要になったコメントアウトしているコードは消したり、使わない変数は消したり、冗長な記述は減らしたり、ネーミングを一般的な規約に合わせるとか、そういう細かい部分は気を配った方がいいかなと思います。他人とソースをやりとりする際にスムーズになります。 仕事だとめっちゃ怒られる事もあります。 知り合いは半角スペース一個余分に多かった事で反省文書かされたと言ってました

bakabon_X
質問者

補足

OKTaro-さま 毎度、お世話になります。 Q2)の質問の件  質問のあと、自分なりにコードを考えていました(下記の添付をご覧ください)。  コメント頂けますと大変有難いです。  コンソール出力部分を2箇所コメント化しまして、サイクル時間は約770us程度でした。  この値は遅い感じですね、何処かに不具合があるかもしれません。 >仕事だとめっちゃ怒られる事もあります。 知り合いは半角スペース一個余分に多かった事で反省文書かされたと言ってました <---企業ですから、そうゆう事も必要かも知れませんね? Q4)私のjavaの開発環境は、Windows7+EclipseのPleiades44です。   もし出来れば貴方の、timerの時間が略正確だったと言われていました、   環境を教えて頂けないでしょうか? 次は余談です。 日本で電子産業が何とか維持できているのは、ドコモが国産品のchipを使用しているからかも 知れません。日本の半導体は、価格と先進性の点で外国に太刀打ちできないようです。 私はARMプロセッサー(LPC1831)のシステムを開発したことがありますが、半導体は全て 欧米製とならざるを得ませんでした。お気に触りましたら、御免なさい。 東芝では無いですが、企業の上層部の出来ることは、社員に発破を掛ける ことかも知れませんね? //=========================== import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.Timer; class T_threadC { static int CNT=20000; volatile static int DATAX=-1; public static void main(String args[]) { new rcvInterrupt().start(); } } class genInterrupt extends Thread implements ActionListener{ //class rcvInterruptより起動される public static Timer timer; private Thread target; volatile static int ptrW=0; volatile static int ptrR=0; volatile static int H[]=new int[T_threadC.CNT]; genInterrupt(rcvInterrupt targetx) { this.target = targetx; timer = new Timer(1 , this); timer.start(); } public void actionPerformed(ActionEvent e){ timer.stop(); //一度に20個のデーターを作成しているわけは、タイマーの割込み時間は長く、Debug時間を短縮するためです。 //実際のAppに於きましては、USBの読込み(readBulk)を使用していますので、0.6ms強で割込みが発生します。 for(int i=0; i<20; i++){ H[ptrW]=T_threadC.DATAX++; ptrW++; if(ptrW>=T_threadC.CNT){ ptrW=T_threadC.CNT-1; } } // System.out.println("================actionPerformed ptrW="+ptrW); //コメント化 timer.start(); } public void run() { System.out.println("genInterupt start"); // rcvInterruptが終了するまで繰り返す while (target.isAlive()) { // Thread.sleepで停止していたらinterrupt if (target.getState() == Thread.State.TIMED_WAITING){ if(ptrW!=ptrR){ target.interrupt(); ptrR++; } } //if (target.getState() == Thread.State.TIMED_WAITING){ } //while (target.isAlive()) { System.out.println("End of job"); System.exit(0); //************************** } //public void run() { } //class genInterrupt extends Thread { class rcvInterrupt extends Thread { // volatile boolean isWaited; int ii; public void run() { new genInterrupt(this).start(); //genInterruptを起動 System.out.println("=============new genInterrupt(this).start()"); long start=System.currentTimeMillis(); for (int i = 0; i <T_threadC.CNT; i++) { try { sleep(1000); } catch (InterruptedException e1) { // System.out.println("get interrupt cnt=" + i+" H="+genInterrupt.H[i]); //コメント化 } } //for long end=System.currentTimeMillis(); double T1=(double)(end-start)*1000.0/(double)T_threadC.CNT; double T2=(double)(end-start)/(double)T_threadC.CNT;; System.out.println("Cyclle time[us] T1="+T1); System.out.println("Cyclle time[ms] T2="+T2); } //public void run() { } //class rcvInterrupt extends Thread { 以上、宜しくお願いします。

  • OKTaro-
  • ベストアンサー率50% (36/72)
回答No.2

以前の質問のお礼にありましたタイマーの件についてお答えします まず私の環境では一度もinterruptされる事なく処理がループしていました。 原因は以下です int ptrR = 0; int ptrW = 0; この2つの変数に対して volatile int ptrR = 0; volatile int ptrW = 0; このようにvolatile修飾子をつける必要があります。 2つの異なるスレッドで同じ変数を参照する場合にこの修飾子をつけないと、値を正しく参照しない場合があります。 これをつけた結果、私の環境ではTimerはほぼ1ms間隔で処理を行っていました。 100msになってしまうと言っていた原因として考えられるのは ・volatile修飾子がついていないので、値の変更に気づけず無駄にループを繰り返していた ・単純に動作環境のスペックの問題 のどちらかだと思います。

bakabon_X
質問者

お礼

OKTaro- さま 毎度、お世話になります。 volatile属性をつけてトラーしましたが、やはり1msのタイマーが100ms位掛かっている 様です。 私の環境は、タイマーに関しまして、問題があるような感じです。 つまり、タイマーのcheckプログラムでも同様に旨く行きませんでしたが、 1msが100msになるような、酷い物では有りませんでした。 ・単純に動作環境のスペックの問題 <---ご指摘のこれかも知れません 以上

bakabon_X
質問者

補足

OKTaro-さま timerの件、回答有難うございます。 タイマーの精度につきましては、諦めて居た所ですが、volatile修飾子をつけまして 再度トライしてみます。 以上

  • OKTaro-
  • ベストアンサー率50% (36/72)
回答No.1

とりあえずポーリングしてsleep中であればinterruptするのであればこんな感じで class T_thread { public static void main(String args[]) { new rcvInterrupt().start(); } } class genInterrupt extends Thread { private Thread target; genInterrupt(rcvInterrupt targetx) { this.target = targetx; } public void run() { System.out.println("genInterupt start"); // rcvInterruptが終了するまで繰り返す while (target.isAlive()) { // Thread.sleepで停止していたらinterrupt if (target.getState() == Thread.State.TIMED_WAITING) target.interrupt(); } } } class rcvInterrupt extends Thread { volatile boolean isWaited; public void run() { new genInterrupt(this).start(); for (int i = 0; i < 10; i++) { try { sleep(1000); } catch (InterruptedException e1) { System.out.println("get interrupt cnt=" + i); } } } } 余談 先日は風邪を引いてしまい、放置になってしまいました。 あと、BA選ぶとクローズされてしまうので、回答者は追記が一切できなくなりますb

bakabon_X
質問者

お礼

OKTaro-さま 下記のコードは、rcvInterruptの受信を確認して、送信を行なう様に変更したものです。 20000回送信を行なってみましたが、受信漏れはありませんでした。 Q1)この変更コードで受信漏れは、無いものと考えて宜しいでしょうか? Q2)rcvInterruptに於ける受信を確認を確認することなく、送信側でDATAXの値を0から   19999に順次カウントアップしまして、その都度target.interrupt()で割込みを掛ける   方法はありますでしょうか? Q3)コードの旨くない所があれば、ご指摘頂けますと大変有り難いです。 以上、お手数ですが宜しくお願いします。 class T_threadC { static int CNT=20000; static int DATAX=-1; static boolean transfered=true; public static void main(String args[]) { new rcvInterrupt().start(); } } class genInterrupt extends Thread { //class rcvInterruptより起動される public static Object timer; private Thread target; genInterrupt(rcvInterrupt targetx) { this.target = targetx; } public void run() { System.out.println("genInterupt start"); // rcvInterruptが終了するまで繰り返す while (target.isAlive()) { // Thread.sleepで停止していたらinterrupt if (target.getState() == Thread.State.TIMED_WAITING){ if(T_threadC.transfered==true){ T_threadC.transfered=false; T_threadC.DATAX++; target.interrupt(); // System.out.println("target.interrupt() DATAX="+T_threadC.DATAX); } //if(T_threadC.transfered==true){ //target.interrupt(); } //if (target.getState() == Thread.State.TIMED_WAITING){ } //while (target.isAlive()) { System.out.println("End of job"); System.exit(0); //************************** } //public void run() { } //class genInterrupt extends Thread { class rcvInterrupt extends Thread { // volatile boolean isWaited; public void run() { new genInterrupt(this).start(); //genInterruptを起動 long start=System.currentTimeMillis(); for (int i = 0; i <T_threadC.CNT; i++) { try { sleep(1000); } catch (InterruptedException e1) { T_threadC.transfered=true; System.out.println("get interrupt cnt=" + i+" DATAX="+T_threadC.DATAX); } } //for long end=System.currentTimeMillis(); double T=(double)(end-start)*1000.0/(double)T_threadC.CNT; System.out.println("Cyclle time[us] T="+T); } //public void run() { } //class rcvInterrupt extends Thread {

bakabon_X
質問者

補足

OKTaro-さま ご返事、有難うございます。 貴方のご回答は、注意深く読ませて頂いております。 前回のsyncronozedの回答も、そのコードにバッファー関係を追加してみました。 今回の、ご回答も、勉強させて頂きます。 風邪をひかれたのことですが、体調管理には十分注意することが大切で、 油断とか過信が一番危険です。 以上

関連するQ&A

  • javaの割込みのcatchに関する質問

    下記のコードはgenInterruptにて、割込みを10回発生させ、rcvInterruptでその 割込みをcatchするものです。 割込みの発生周期が1msの場合は、割込みのcatchは略10回受取ることが出来ますが、 割込みの発生周期が短い場合は、最初の2、3個受取るのみです。 Q1)割込みの発生周期が1msの場合には、全ての割込みをcatchすることが出来ますか? //========================== //Project: Interrupt(受信側セット)の確認 class T_thread extends Thread{ static int TIMES=20; public static void main(String args[]){ rcvInterrupt obj=new rcvInterrupt(); obj.start(); for (int i = 0 ; i <TIMES ; i++){ try{ Thread.sleep(1); //System.out.println("main: "+TIMES+"20回の1msタイマー待ち"); }catch(InterruptedException e){ } } } } class genInterrupt extends T_thread{ private Thread target; genInterrupt(Thread targetx){ this.target=targetx; } public void run(){ System.out.println("genInterupt start"); for (int i=0; i<10; i++){ try{ Thread.sleep(0); //割込みが殆ど捕らえられない //Thread.sleep(1); //割込みが全て捕らえられない事がたまにある target.interrupt(); } catch(InterruptedException e){ } } } } class rcvInterrupt extends T_thread{ int cnt=0; public void run(){ genInterrupt obj=new genInterrupt(Thread.currentThread()); obj.setPriority(Thread.MAX_PRIORITY); obj.start(); System.out.println("receiveInterupt start"); for (int i=0 ; i<20 ; i++){ try{ Thread.sleep(2); }catch(InterruptedException e){ System.out.println("get interrupt cnt="+cnt++); } } } } //========================== 以上、宜しくお願いします。

    • ベストアンサー
    • Java
  • javaのスレッドの割込みについて

    javaのスレッド割込みに関する初心者の質問です。 割込みの発生元でCNTに値を設定し、割込みの受信元でCNTの値を読込み、表示しています。 下記のコードを参照ください。 Q1)CNTの値の設定と読込みで競合が発生する様なことはありませんか? 又は、処理が停滞するとか 以上、お手数をお掛けしますが、宜しくお願いします。 //割り込を発生するスレッド class threadA extends base{ private Thread target; public threadA(Thread targetA){ target = targetA; } public void run(){ for(int i = 0; i < 8;i++){ try{ System.out.print("."); Thread.sleep(1); CNT=i; target.interrupt(); }catch(InterruptedException e){ System.out.println("今割り込まれました: thread"); } } } } //スレッドからの割り込みを受信するルーチン class Sample108{ public static void main(String args[]){ //for(int i=0; i<2; i++){ classA obj = new classA(); obj.threadStart();//割り込みを受けるルーチン、この中で、割り込みを発生するルーチンを起動している //} } } //割り込みを受けるルーチン class classA extends base{ void threadStart(){ System.out.println("Start: main****"); threadA obj = new threadA(Thread.currentThread()); obj.start(); //Thread起動 //mainのルーチン for(int j = 0;j < 20; j++){ try{ Thread.sleep(1); System.out.print("*"); }catch(InterruptedException e){ System.out.println("今割り込まれました: classA CNT="+CNT); } } } } 以上

    • ベストアンサー
    • Java
  • スレッド1とスレッド2を交互に実行するには?

    スレッド1→スレッド2→スレッド1・・・と同期を取り合いながら交互にスレッドを動かしたいのですが、Thread.getState()を用いないで実現するよい方法はないでしょうか? どうしてもデッドロックが発生しうる方法しか思いつかず困っています。 例えば以下のプログラムで1212と交互に表示させたい場合です。 以下のプログラムは当然デッドロックになりますが、やりたいことを伝えるために載せておきます。 Object obj; //スレッド間通信用のobject class Test1 extends Thread {  public void run() {   while(true) {    System.out.print("1");    synchronized (obj) {     obj.notify();//相手をnotifyして     obj.wait();//自分はwait    }   }  } } class Test2 extends Thread {  public void run() {   while(true) {    System.out.print("2");    synchronized (obj) {     obj.notify();     obj.wait();    }   }  } } new Test1().start(); new Test2().start();

    • ベストアンサー
    • Java
  • Threadに関するの質問

    このプログラムに synchronized , wait(), notify()を加えることで、 stackBody[]配列をオーバーやアンダーフローしないようにできるのでしょうか。お助け下さい! public class test { public static void main(String args[]) { Stack stack = new Stack(5); Pusher pusher = new Pusher(stack); Popper popper = new Popper(stack); pusher.start(); popper.start(); } } class Stack { private int stackSize; private int stackPointer; private int stackBody[]; public Stack(){ this(10); } public Stack(int size){ stackSize = size; stackBody = new int[size]; stackPointer = 0; } public void push(int value){ if(stackSize == stackPointer){ // } stackBody[stackPointer++] = value; } public int pop(){ if(stackPointer == 0){ // } return stackBody[--stackPointer]; } } class Pusher extends Thread { Stack s; public Pusher(Stack s) { this.s = s; } public void run() { int n, interval; for(int i = 0; i < 10; i ++) { n = (int)(100.0 * Math.random()); interval = (int)(100.0 * Math.random()); s.push(n); System.out.println("Pusher:" + n); try{ Thread.sleep(interval); }catch(InterruptedException e) {} } System.out.println("Push 終了"); } } class Popper extends Thread { Stack s; public Popper(Stack s) { this.s = s; } public void run(){ int n, interval; for(int i = 0; i < 10; i++){ interval = (int)(100.0 * Math.random()); n = s.pop(); System.out.println("Popper:" + n); try{ Thread.sleep(interval); }catch(InterruptedException e) {} } System.out.println("Popper 終了"); } }

    • ベストアンサー
    • Java
  • [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 Threadのsleepを途中で止める方

    今、訓練校に通っていて課題をだされていますが、どうもうまく行きませんのでお知恵を拝借したく思います。  java Threadのsleepを使用し、クイズの回答を10秒以内で答えるというものですが、 途中で入力をすると、次の問題の回答時間が異様に早くなり1秒ではなくなってしまいます。  こういう場合、入力をすれば、runメソッドが終わるというプログラムはどうやって書けばいいのか教えて頂きたく思います。 どうぞよろしくお願いいたします。 <下記、threadの部分だけですが、パッケージを使用するという課題のため無理やり使っています。> package pa; public class CountTest extends Thread { public void start() { super.start(); } public void run() { for (int i=10; i >= 1; i--) { try{ sleep(1000); System.out.print("⇒" ); }catch(InterruptedException e){} } System.out.println(""); for (int i=1; i >= 1; i--) { / } System.out.println("Time up "); System.out.println(""); System.out.println("1-4で答えを記入してください"); }

    • ベストアンサー
    • Java
  • スレッドの実行結果表示順について

    java学習超初心者です。一人で勉強しています。 以下のコードの実行結果に対して質問があります。 class MyThread extends Thread{ public void run(){ for (int i=1;i<=8; i++){ System.out.println("*************************サブスレッドも動いています********" + i); } } } public class JaThrd1{ public static void main (String args[]){ MyThread aa = new MyThread(); aa.start(); for(int i=1; i<=12; i++){ System.out.println("メインスレッドで仕事中です" + i); } } } 実行結果が↓です *************************サブスレッドも動いています********1 メインスレッドで仕事中です1 *************************サブスレッドも動いています********2 メインスレッドで仕事中です2 *************************サブスレッドも動いています********3 メインスレッドで仕事中です3 *************************サブスレッドも動いています********4 メインスレッドで仕事中です4 *************************サブスレッドも動いています********5 メインスレッドで仕事中です5 *************************サブスレッドも動いています********6 メインスレッドで仕事中です6 *************************サブスレッドも動いています********7 メインスレッドで仕事中です7 *************************サブスレッドも動いています********8 メインスレッドで仕事中です8 メインスレッドで仕事中です9 メインスレッドで仕事中です10 メインスレッドで仕事中です11 メインスレッドで仕事中です12 なぜこのような順番の結果になるのでしょうか? 交互に表示されることがわかりません。

    • ベストアンサー
    • Java
  • デッドロックに関して1

    下記のサンプルソースは、デッドロックを起こすソース なのですが、 public class Deadlock extends Thread { public static Object l1 = new Object(); public static Object l2 = new Object(); private int index; public static void main(String[] a) { Thread t1 = new ThreadA(); Thread t2 = new ThreadB(); t1.start(); t2.start(); } private static class ThreadA extends Thread { public void run() { synchronized (l1) { System.out.println("スレッド1: l1に対するロックを取得"); try { Thread.sleep(10); } catch (InterruptedException e) {} System.out.println("スレッド1: l2のロックの開放待ち"); synchronized (l2) { System.out.println("スレッド1: l1、l2に対するロックを取得"); } } } } private static class ThreadB extends Thread { 文字数オーばーのため削除 } これを参考に、Junitでデッドロックを起こすサンプルを作りたいです。 MultithreadedTestCaseと ControllableTestThreadを使い サンプルを作りたいのですが、 英語が良くわからず苦戦しております。 なにか、よいアドバイスをいただけませんでしょうか? よろしくお願いします

    • ベストアンサー
    • Java
  • Thread のターゲット切り替えについて

    以下のようなソースを書きました。Runnableを実装しているクラスをスーパークラスに持つクラスThreadSampleChildをインスタンス化した後にそのクラスのThreadを実行し、途中で親クラスのスレッドに切り替えることを目的としているのですが、切り替わらずに子クラスのThreadが引き続き継続してしまいます。 理由はなんとなくわかるのですが。子クラスから親クラスのThreadを実行させるためにはどう工夫すればよいのでしょうか? class ThreadSample implements Runnable { Thread threadp; ThreadSample() { } public void run() { while(true) { try { System.out.println("Parent"); Thread.sleep(500); } catch(Exception e) { break; } } } public void makingThreadParent() { threadp = new Thread(this); } } class ThreadSampleChild extends ThreadSample { Thread threadc; ThreadSampleChild() { } public void run() { while(true) { try { System.out.println("Child"); Thread.sleep(500); } catch(Exception e) { break; } } } public void makingThreadChild() { threadc = new Thread(this); } public void exe() { while(true) { threadc.start(); try { Thread.sleep(10000); } catch(Exception e) { } threadc.interrupt(); makingThreadParent(); System.out.println("Thread Change !!!!"); threadp.start(); try { Thread.sleep(10000); } catch(Exception e) { } threadp.interrupt(); } } public static void main(String args[]) { ThreadSampleChild tsc = new ThreadSampleChild(); tsc.makingThreadChild(); tsc.exe(); } }

    • ベストアンサー
    • Java
  • 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

専門家に質問してみよう