質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Q&A

解決済

1回答

290閲覧

コンストラクタに書いたJButtonでnotifyする方法

vicreo32

総合スコア15

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

0グッド

0クリップ

投稿2017/07/03 09:00

###前提・実現したいこと
課題で簡単なStopwatchを作っています。
JButtonで作ったスタートボタンを押すと、waitになっていたオブジェクトをnotifyするように作りたいです。
デッドロックが原因だと予測しているのですが、その回避の方法がわかりません。
また、今回質問している箇所の他にもおかしな箇所があれば教えてほしいです。

###発生している問題・エラーメッセージ
ボタン自体は動作しているのですが、notifyが動作しません。
おそらく、waitとnotifyどちらもsynchronizedにしているので、デッドロックになってしまっていると予測しています。

###該当のソースコード

java

1public class stopwatch2 extends JPanel{ 2 static JLabel label; 3 JButton b1,b2,b3; 4 public static final int FPS = 0; 5 private static long startTime; 6 private static boolean isRunning = false; 7 private static long time; 8 public stopwatch2(){ 9 10 label =new JLabel(String.valueOf(time)); 11 b1 = new JButton("Start"); 12 b1.addActionListener( 13 new ActionListener(){ 14 public synchronized void actionPerformed(ActionEvent event){ 15 isRunning = true; 16 notify(); 17 } 18 }); 19 b2 = new JButton("Stop"); 20 b2.addActionListener( 21 new ActionListener(){ 22 public void actionPerformed(ActionEvent event){ 23 isRunning = false; 24 } 25 }); 26 b3 = new JButton("Reset"); 27 setLayout(new BorderLayout()); 28 add(label,BorderLayout.NORTH); 29 add(b1,BorderLayout.CENTER); 30 add(b2,BorderLayout.EAST); 31 add(b3,BorderLayout.SOUTH); 32 } 33 34 public static void main(String[] args) throws InterruptedException { 35 // TODO Auto-generated method stub 36 JFrame frame = new JFrame("Stopwatch"); 37 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 38 stopwatch2 sw = new stopwatch2(); 39 frame.add(sw); 40 frame.pack(); 41 frame.setVisible(true); 42 System.out.print(isRunning); 43 while(true){ 44 System.out.print(Thread.currentThread()); 45 synchronized(sw){ 46 sw.wait(); //swがついてるメソッドの間はsynchronizedされる 47 } 48 sw.startTime = System.currentTimeMillis();//ミリ単位の現在の時間をstartTimeに代入 49 while(sw.isRunning){ //isRunningがtrueの間ループ 50 //ラベルにtimeに入っているものを入れて更新し続ける 51 //stopを押すと、isRunningにfalseを代入してループを止める。 52 sw.label.setText(String.valueOf(System.currentTimeMillis()-startTime)); 53 sw.repaint(); 54 Thread.sleep(1000 / stopwatch2.FPS); 55 } 56 } 57 58 } 59 60} 61

###ツール
eclipseを使っています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

synchronizedの対象オブジェクト(インスタンス)が異なっているのが原因のように思えます。

mainメソッドでsynchronized(sw)としていますが、この際の同期対象オブジェクトはstopwatch2クラスのインスタンスです。それと排他制御をしようとしていると思われる箇所はstopwatch2のコンストラクター内での以下のコードだと思います。しかし、こう書くと同期対象インスタンスはActionListenerの無名クラスのインスタンスとなります。それぞれ違うインスタンスに対してsynchronizedしているので同期になっていないと思います。

Java

1b1.addActionListener( 2 new ActionListener(){ 3 public synchronized void actionPerformed(ActionEvent event){ 4 isRunning = true; 5 notify(); 6 } 7 });

とりあえずの対処として、同一のインスタンスに対してsynchoronizedを用いるようにしてみてはどうでしょう。(それで期待通り動くかどうかまでは確認していません)

Java

1b1.addActionListener( 2 new ActionListener(){ 3 public void actionPerformed(ActionEvent event){ 4 Object lock = stopwatch2.this; //このオブジェクトを同期に使う 5 synchoronized (lock) { 6 isRunning = true; 7 lock.notify(); 8 } 9 } 10 });

投稿2017/07/03 10:05

編集2017/07/03 14:58
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

vicreo32

2017/07/03 14:53

回答ありがとうございます。 早速試してみたところ、startボタンを押すと、java.lang.IllegalMonitorStateExceptionというエラーが出ました。 解決策をご存知でしたら教えていただけるとありがたいです。
KSwordOfHaste

2017/07/03 14:56

失礼しました。notifyの方もなおさなければなりませんでしたね。回答を修正します。
vicreo32

2017/07/03 23:51

無事にnotifyできました! ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問