• ベストアンサー

再度、スレッドが実行中かどうかの確認

一度質問したことですが、再度質問させていただきます。 過去の質問は以下です。 http://oshiete1.goo.ne.jp/qa5528714.html 過去の質問を参考に、以下のように実装しました。 public class TEST{  public boolean testMe(){   Runnable runnable = /* 省略 */;   Thread thread = new Thread(runnable);   boolean alive = thread.isAlive();   /* 必ずfalseになってしまう */   if(!alive){    thread.start();    return true;   }   return false;  } } public class TEST2 implements Runnable{  public void run(){   /* 処理 */  } } 上記の通りだと「thread.isAlive()」が必ずfalseで返ってきます。 また、Executorを利用した実装も試しました。 /* 処理を省略 */ ExecutorService executorService = Executors.newSingleThreadExecutor(); Runnable runnable = /* 省略 */; // シャットダウン結果 boolean exeShutdown = executorService.isShutdown(); /* 一度シャットダウンすると、ずっとtrueになってしまう */ if(!exeShutdown){  // 実行  executorService.execute(runnable);  // シャットダウン  executorService.shutdown(); } 一度は実行されるのですが、 その後は「executorService.isShutdown()」がtrueしか返しません。 なので、一度しか実行できません。 再度、知恵を貸していただければと思います。 よろしくお願い致します

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

  • ベストアンサー
  • salsberry
  • ベストアンサー率69% (495/711)
回答No.5

元の質問には「「一度ボタンを押してスレッドが実行中の場合は処理を実行しない」という処理を実装したい」と書かれていますが、これは (a) 実行中のスレッドが終了するまでは、何度ボタンを押しても単に無視する (b) スレッド実行中にボタンが押された場合は、新しいスレッドを作るが今実行中のスレッドが終了するまで処理開始を遅らせる のどちらでしょうか? (a)だったら、最後に作ったスレッドを覚えておく変数を用意すればいいだけ。 public class TEST { private static Thread lastThread = null; public boolean testMe() { if (lastThread != null && lastThread.isAlive()) { return false; } else { Thread newThread = new Thread(...); newThread.start(); lastThread = newThread; return true; } } (b)だったら、一番手抜きな方法はrun()メソッドの中身を全て排他処理にしてしまうこと。これなら、run()の内容を2つ以上のスレッドが同時に実行することができません。 public class TEST2 implements Runnable { private static Object lock = new Object(); public void run() { synchronized (lock) { /* 処理 */ } } }

green64
質問者

お礼

回答ありがとうございます。 私の求めている実装は(a)です。 書いていただいた処理を試してみます。 余談ですが、独自に実装した処理で、何とか出来そうな感じがしています。

green64
質問者

補足

独自に実装した処理でも出来ました。 しかし、あまり見栄えが良くなかったので、salsberry様の処理を使用させていただきます。 回答くださった皆様、この場を借りて、再度お礼いたします。 回答ありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (4)

  • tom11
  • ベストアンサー率53% (134/251)
回答No.4

thread.start()をif文で、囲んでも意味ないような!! thを5秒生きさせ、10秒後生きているかどうかの確認 Thread th = new Thread(new Runnable() { public void run() { try { Thread.sleep(5000); } catch (InterruptedException ex) { Logger.getLogger(goo_test10.class.getName()).log(Level.SEVERE, null, ex); } } }); th.start(); System.out.println(th.isAlive()); try { Thread.sleep(10000); } catch (InterruptedException ex) { Logger.getLogger(goo_test10.class.getName()).log(Level.SEVERE, null, ex); } System.out.println(th.isAlive()); 実行結果 true false

green64
質問者

お礼

回答ありがとうございます。 threadを5秒生きさせた場合、5秒以内にボタンを連打するとthreadが実行されないでしょうか。 しかし、これを応用すれば実装できそうな気がします。

全文を見る
すると、全ての回答が全文表示されます。
  • askaaska
  • ベストアンサー率35% (1455/4149)
回答No.3

こういうものを作ったらどお? クラス名ThreadManager(シングルトン) メソッド ・synchronized add(Thread)   新規スレッドを実行したくなったらThreadManagerにaddする。 ・start   ThreadManagerに管理されているThreadを順に実行する。   1つ実行し終わったとき、管理されている次のThreadがあったらそれを実行   終わったThreadはThreadManagerから削除する。 こんなものを用意すればきっとうまいこといけるはずよ。

green64
質問者

お礼

回答ありがとうございます。 「ThreadManagerにaddする」が、どのようなものか、いまいち不明です。 何かthreadに追加する実装があるのでしょうか。 「synchronized」や「addする」等を使用することで出来るようなので試してみます。

全文を見る
すると、全ての回答が全文表示されます。
  • precog
  • ベストアンサー率22% (966/4314)
回答No.2

共有変数使えばいいんじゃないかと思うんですけど、、、 isAliveは http://www.wakhok.ac.jp/biblion/1996/JavaAppli/node35.html >スレッドが起動されて、かつ、ストップされていなければ、 trueを返します。 つまり、実行可能状態にあればTRUEを返すわけですから、 >/* 必ずfalseになってしまう */ これは当たり前の話では? (生成された直後は実行可能状態ではないのでは?) isAliveは直ちに値を返すので、この関数で待とうとするとポーリングする必要が出てきますよね。これはスレッドプログラミングとしてはヘタクソなやり方だと思います。 そもそも1スレッドしか起こさないなら最初からマルチスレッドにする必要はないと思います。ライトウェイトとはいえコンテクストスイッチングにはコストが掛かりますので。 練習の意味でというならセマフォとかミューテックスで待ち合わせるべきと思います。それではメインがスタックして困るというなら、それはスレッドの分割の仕方が悪いのか、アーキテクチャの「ねり」が足りないのでは? Javaがどこまでサポートするのか知らないのですけど、キューなどの機構も考えてみては?

green64
質問者

補足

回答ありがとうございます。 isAliveはstart後でなければtrueにならないのですね。 共有変数とは Thread thread = null; public boolean testMe(){  /* 省略 */  if(thread == null){   thread.start();   return true;  }  return false; } 上記のようなことでしょうか? 上記である場合は、Executorと同じく一度実行すると二度と実行されません。 そもそも、 「runメソッドの処理が実行中の場合に、スレッドを実行するとrunメソッドの処理は実行されない」 ということは可能なのでしょうか?

全文を見る
すると、全ての回答が全文表示されます。
  • askaaska
  • ベストアンサー率35% (1455/4149)
回答No.1

最初のスレッドを開始していないからよ。

green64
質問者

補足

回答ありがとうございます。 「最初のスレッドを開始」ということは Thread thread = new Thread(runnable); // 開始 thread.start(); boolean alive = thread.isAlive(); if(!alive){ /* 以下省略 */ 上記のようなことでしょうか?

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • スレッドが実行中かどうかの確認

    画面の中にボタンを作成し、そのボタンを押すとスレッドが実行される機能を作成しました。 「一度ボタンを押してスレッドが実行中の場合は処理を実行しない」 という処理を実装したいです。 上記の処理を以下のソースで考えていますが(1)の部分がわかりません。 そもそも(1)のようなことが可能かもわかっていない状況です。 (1)のようなことは可能なのでしょうか? どなたか、知恵を貸していただければと思います。 よろしくお願い致します。 /* ソース */ public class ExThread1 extends Thread{  public void run() {   // 処理  } } public class TEST {  public static void main(String[] args){   ExThread1 thread1 = new ExThread1();   // (1)スレッドが実行中ならstartしない   if(スレッドが実行中ではない){    thread1.start();   }  } }

    • ベストアンサー
    • Java
  • applet

    スレッドを使ってタイマーを作ろうと思っています。なぜか、ゆっくりとしかできないのですが・・。よろしくお願いします。 class TimerA implements Runnable { private boolean flg = true; private int time = 6000; public boolean isFlg() { return flg; } public int getTime(){ return time; } public void run() { for(;time > 0; time--) ; flg = false; System.out.println(time); } }

  • スレッドの停止方法の確認

    スレッドの停止方法の質問。 停止可能なスレッドを、私は以下のような形で書く事が多いのですが、インターネットで同様な コードを検索すると、2行目の停止フラグの宣言に volatile が無いものが無数に見つかります。 JSR-133 の簡単な解説を読んで、私なりに解釈した結果 volatile は必要と判断したのですが、これは間違いなのでしょうか? volatile は多少重たいので、できれば外したいのですが、 外してよい根拠が見つかりません。 真偽をご存知の方、よろしくお願い致します。 class MyThread extends Thread { private volatile boolean done = false; public void terminate(){ done = true; interrupt(); } public void run(){ while(!done){ //処理 } } }

    • ベストアンサー
    • Java
  • スレッドの削除について

    永久ループのあるスレッドがあって、必要なくなったら、永久ループをブレイクさせようと思ってました。このスレッドのクラスのグローバル変数 boolean kaijo; があって、普段は false でブレイクさせたいときだけ、 true にしようと思ってました。このクラスはインスタンス化しているので、 オブジェクト.kaijo=true; という風にして、スレッドをブレイクさせようと思っていましたが、なぜかkaijoはfalseのままです。確かに オブジェクト.kaijo=true; と代入したはずなのですが、、どう思われますか? またスレッドを停止、あるいは破棄するメソッドはありますか?推奨されている範囲内で。

    • ベストアンサー
    • 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
  • プログラムのスレッド化について。

    以下の処理をスレッド化しようとしています。 public class FCP{ int N=10 long LOOP_MAX=100 double x[][] = new double[N][4] int g[][] = new int[N][4] boolean y[][] = new boolean[N][4]//出力 boolean A[][] = new boolean[N][10] double T=0.5 Set_Adjacent_Matrix() //A配列にtrueとfalseを代入 Set_initial_value() //y配列に初期値を代入(Math.random()>0.5) g1(int i, int j) //k<4 sum=1 if( y[i][k] == true ) --sum return(double)sum g2(int i, int j) //k<N sum=0 if( y[i][j] == true ) if( y[k][j] == true && A[i][k] == true ) --sum return(double)sum Display_output() //結果表示 if( y[i][j] ) System.out.print("0") else System.out.print(".") public static void main(String args[]) { long loop; int i, j, k; Set_Adjacent_Matrix(); Set_initial_value(); for( loop=0; loop<LOOP_MAX; loop++ ){ for( i=0; i<N; i++ ){ for( j=0; j<4; j++ ){ x[i][j] = g1( i, j ) + g2( i, j ); if( y[i][j] ){ x[i][j] += T; }else{ x[i][j] -= T; } if( x[i][j] > 0.0){ y[i][j] = true; }else{ y[i][j] = false; } } } Display_output(); } } 今回Threadクラスの継承を使ってスレッド化しようと考えました。runメソッドには上のプログラムのmain部分の処理をさせようと思っています。そしてstartメソッドで必要な数(Nの値=10コ)のスレッドを生成しrunメソッドを実行する。 と、ここまではわかったのですが、「生成された各スレッドの番号を保持し、そのスレッドに担当させる処理を決める」という部分をどうすればいいのかわかりません。 「i(1~10)番目のスレッドはN(1~10)列目の処理を担当している」という風にするにはどうしたらいいのでしょうか? よろしくお願いします。

    • ベストアンサー
    • Java
  • スレッドの待機と再開

    お世話になります。 マルチスレッドのプログラムで悩んでいます。 public class ThreadLocker {  private static boolean isLocked = false;    public static void lock() {   isLocked = true;   while(isLocked) { ; }  }    public static void unlock() {   isLocked = false;  } } まず、このようなクラスを定義しました。そして複数のスレッドが ThreadLocker.lock(); を呼び出して、処理の進行をストップしている状態があるとします。この状態に対して、とある別のスレッドが ThreadLocker.unlock(); を呼び出すと、それまで無限ループしていたスレッドが解放されて処理を始める、という感じです。 この方法を試してみましたが、無限ループで何も処理をしていないとは言え、リソースを食いまくっているようで、マシンが重くなってしまいました。 そこで、スレッドの待機・再開を行う事ができる wait / notify(All?) メソッドを使用すれば良いのではないかと考えたのですが、具体的な方法が分からず、質問させていただきました。 具体的に、どのインスタンスの wait 及び notify(All?) を呼び出せば良いのかが分かりません。 APIリファレンスの「現在のスレッドはこのオブジェクトのモニターのオーナでなければなりません。」の意味もよく分かりません。 ちなみに、待機しているスレッドは複数あり、class Lock の method execute 中で ThreadLocker.lock() しているとします。 また、再開を促すスレッドは1つで、class Unlock の method execute 中で ThreadLocker.unlock() を呼び出すものとします。 そして、それぞれのスレッドは、お互いのインスタンスを知りません。(説明しづらいので、補足要求があれば、ソースで示します。) よろしくお願いいたします。

    • ベストアンサー
    • Java
  • スレッドについての質問です。

    下記のロジックを見ていただきたいのです。 スレッドがnullの間はrunが動いています。 問題は一番下に記載した"stopplay()"というメソッドだと思われます、スレッドを停止して直ぐにまた動かしていますがどうもスレッドが二つ動いている様子です。なぜでしょうか? ************************************************** //最初にスレッドを開始します。 public init(){ play(); } ************************************************** //スレッドのON OFF public void threadOnOff(boolean sw) { if(sw == true){ thread =new Thread(this); thread.start(); } else { thread = null; } } ************************************************** //スレッド開始 public void play(){ threadOnOff(true); } ************************************************** //スレッド停止 public void stop(){ threadOnOff(false); } ************************************************** //runメソッド  public void run(){ String mode = ""; while(thread != null){ try { thread.sleep(500); //0.5秒間隔で動きます。 mode = modeRequest(); if(mode.startsWith("STOP") == true) { //スレッド停止 threadOnOff(false); } } catch (InterruptedException ie) {} } } ************************************************** //問題のメソッドです。 public void stopplay(){ stop(); play(); }

    • ベストアンサー
    • Java
  • これを実行するには

    私の知り合いにプログラムを作ってもらったのですが、どうすればよいのかまったくわかりません。どうすればよいでしょうか。 ↓このようなものです。 #include <stdio.h> #include <stdlib.h> #include <time.h> typedef int BOOLEAN; BOOLEAN TRUE = 1; BOOLEAN FALSE = 0; int main(void) { int wc,c,rnd; BOOLEAN dec[50] = {FALSE}; c = wc = 0; dec[0] = TRUE; srand(time(NULL)); while(1){ rnd = rand() % 49; if(dec[rnd] == FALSE){ dec[rnd] = TRUE; if(wc == 6){ printf("%0*d\n",2, rnd); c++; wc = 0; if(c == 49){ break; } } else{ printf("%0*d,",2, rnd); c++; wc++; } if(c == 24){ printf("00,"); c++; wc++; } } } return 0; }

  • 複数のスレッドから1つのスレッドの関数を呼び出す場合、順次呼び出したいのですがどうしたらいいですか?

    スレッドが8個あったとして スレッド1、スレッド2、スレッド3から スレッド5の関数を呼び出したとする。 この場合どうなるか教えてください。 どうなるというのは例として スレッド1 → getHoge() を呼び出した。 スレッド2 → getHoge() を呼び出した。 スレッド3 → getHogeHoge() を呼び出した。 場合、 スレッド2がgetHoge()を呼び出したときに、 スレッド1が呼び出したgetHoge()が終了していないとすると 1.スレッド1の呼び出したgetHoge()が終了後スレッド2が呼び出した getHoge()を実行していくのか? 2.スレッド1の呼び出したgetHoge()とスレッド2の呼び出したgetHoge()が並列処理されるのか? public class TThread extends Thread { (関数は質問趣旨とは関係ないので省略して書く) public int getHoge(); public int getHogeHoge(); }

    • ベストアンサー
    • Java