- ベストアンサー
再度、スレッドが実行中かどうかの確認
一度質問したことですが、再度質問させていただきます。 過去の質問は以下です。 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しか返しません。 なので、一度しか実行できません。 再度、知恵を貸していただければと思います。 よろしくお願い致します
- みんなの回答 (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) { /* 処理 */ } } }
その他の回答 (4)
- tom11
- ベストアンサー率53% (134/251)
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
お礼
回答ありがとうございます。 threadを5秒生きさせた場合、5秒以内にボタンを連打するとthreadが実行されないでしょうか。 しかし、これを応用すれば実装できそうな気がします。
- askaaska
- ベストアンサー率35% (1455/4149)
こういうものを作ったらどお? クラス名ThreadManager(シングルトン) メソッド ・synchronized add(Thread) 新規スレッドを実行したくなったらThreadManagerにaddする。 ・start ThreadManagerに管理されているThreadを順に実行する。 1つ実行し終わったとき、管理されている次のThreadがあったらそれを実行 終わったThreadはThreadManagerから削除する。 こんなものを用意すればきっとうまいこといけるはずよ。
お礼
回答ありがとうございます。 「ThreadManagerにaddする」が、どのようなものか、いまいち不明です。 何かthreadに追加する実装があるのでしょうか。 「synchronized」や「addする」等を使用することで出来るようなので試してみます。
- precog
- ベストアンサー率22% (966/4314)
共有変数使えばいいんじゃないかと思うんですけど、、、 isAliveは http://www.wakhok.ac.jp/biblion/1996/JavaAppli/node35.html >スレッドが起動されて、かつ、ストップされていなければ、 trueを返します。 つまり、実行可能状態にあればTRUEを返すわけですから、 >/* 必ずfalseになってしまう */ これは当たり前の話では? (生成された直後は実行可能状態ではないのでは?) isAliveは直ちに値を返すので、この関数で待とうとするとポーリングする必要が出てきますよね。これはスレッドプログラミングとしてはヘタクソなやり方だと思います。 そもそも1スレッドしか起こさないなら最初からマルチスレッドにする必要はないと思います。ライトウェイトとはいえコンテクストスイッチングにはコストが掛かりますので。 練習の意味でというならセマフォとかミューテックスで待ち合わせるべきと思います。それではメインがスタックして困るというなら、それはスレッドの分割の仕方が悪いのか、アーキテクチャの「ねり」が足りないのでは? Javaがどこまでサポートするのか知らないのですけど、キューなどの機構も考えてみては?
補足
回答ありがとうございます。 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)
最初のスレッドを開始していないからよ。
補足
回答ありがとうございます。 「最初のスレッドを開始」ということは Thread thread = new Thread(runnable); // 開始 thread.start(); boolean alive = thread.isAlive(); if(!alive){ /* 以下省略 */ 上記のようなことでしょうか?
お礼
回答ありがとうございます。 私の求めている実装は(a)です。 書いていただいた処理を試してみます。 余談ですが、独自に実装した処理で、何とか出来そうな感じがしています。
補足
独自に実装した処理でも出来ました。 しかし、あまり見栄えが良くなかったので、salsberry様の処理を使用させていただきます。 回答くださった皆様、この場を借りて、再度お礼いたします。 回答ありがとうございました。