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

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

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

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

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

Q&A

解決済

1回答

2311閲覧

JavaのSwingでパネルの処理を停止させずServerSocket.accept()も並列で処理をさせたい

infologicmation

総合スコア49

Java

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

Swing

SwingはJavaに標準で付属するグラフィック関連のクラスライブラリを指します。

0グッド

0クリップ

投稿2016/10/10 05:57

###前提・実現したいこと
今、JavaのSwingを使って各種ボタンやパネルを構築していっています。そのパネルでサーバー役としての機能を実装しようと思っています。

パネルには接続状況を表示するラベルとサーバー役としての機能を開始するボタンを載せています。
このボタンをクリックしたらServerSocketクラスのaccept()メソッドが起動してクライアントからの接続を待つという状態になりつつも、ラベルには「接続待機中」という文字列を表示するという状況を実現したく思っています。

しかし、私の現在の実装ではボタンをクリックしたら、accept()メソッドが実行されはするものの、クライアントからの接続が来るまで処理を停止するというこのaccept()メソッドの機能故に?パネルの方の処理がなされない…つまり、ラベルに「接続待機中」という文字列が表示されない状況になっています。

どうすればよいでしょうか?

###発生している問題・エラーメッセージ

###該当のソースコード
###試したこと
###補足情報(言語/FW/ツール等のバージョンなど)

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

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

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

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

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

guest

回答1

0

ベストアンサー

UIの処理を行うスレッドはswingではEDT(Event Dispatch Thread)と呼ばれます。EDTでは時間のかかる処理を行ってはいけないという原則があるので、そういう処理は別スレッドで行うという方針になります。以下サーバー処理を行うスレッドをサーバースレッドと呼びます。

サーバースレッドから画面の状態を変える場合はSwingUtilities#InvokeLater/InvokeAndWaitなどを使うと簡単に行えます。逆にEDTから長期間動作しっぱなしのサーバースレッドのようなものへ任意のタイミングで指示をしようとすると若干面倒かも知れません。それ用の便利なクラスもあると思いますが初めてマルチスレッド処理を学ぶケースでは前提知識が少なくその機能の説明自体がわからないこともありそうです。私などはそういったクラスのAPIリファレンスの説明を読んでも最初はちんぷんかんぷんでした。ですのでネットにある記事を手掛かりにするとよいと思います。まずは基本となるThread, synchronizedや複数のスレッドから安全に更新できるデータをサポートするクラス(AtomicXXX)のあたりから学ばれるとよいと思います。なおEDTからサーバースレッドへコマンドを渡す素朴な例を以下に挙げます。Startボタンでサーバー開始、Stopボタンでサーバーを終わらせるといった感じです。(コンパイルしてないので綴りミスなどあるかもしれませんが雰囲気はつかめるかと思います)

java

1// UIのクラス(EDTでのみアクセス可) 2class UI extends JPanel { 3 Server server; 4 JButton btnStart; 5 JButton btnStop; 6 7 UI() { 8 btnStart = new JButton(new AbstractAction("Start") { 9 @Override public void actionPerformed(ActionEvent ev) { 10 btnStart.setEnabled(false); 11 server = new Server(); 12 server.start(); 13 } 14 }); 15 btnStop = new JButton(new AbstractAction("Stop") { 16 @Override public void actionPerformed(ActionEvent ev) { 17 btnStop.setEnabled(false); 18 server.push(Server.Command.Stop); 19 } 20 }); 21 btnStop.setEnabled(false); 22 ... 23 } 24 ... 25} 26 27// サーバースレッドで仕事を行うためのクラス 28public class Server implements Runnable { 29 // サーバーへのコマンド 30 public enum Command { 31 None, 32 Stop, 33 ... 34 } 35 // UIからの指示を受け取るキュー。 36 // LinkedListはスレッドセーフでないのでsynchronizedを用い同期した上でアクセス。 37 // (スレッドセーフなクラスもあるのでそれを使うと同期は不要) 38 Deque<Command> commands = new LinkedList<>(); 39 UI ui; 40 41 public Server(UI ui) { this.ui = ui; } 42 43 public void start(UI ui) { 44 Thread t = new Thread(this); 45 t.setDaemon(true); // このスレッドが残っていても画面を閉じればアプリが終わるように 46 t.start(); 47 } 48 49 // UIスレッドからコマンドをキューに入れる(ごく短い時間で終わる) 50 public void push(Command c) { 51 synchronized (commands) { commands.push(c); } 52 } 53 54 // コマンドをキューから取り出す(ごく短い時間で終わる) 55 private void pop() { 56 synchronized (commands) { 57 return commands.isEmpty() ? Command.None : commands.pop(); 58 } 59 } 60 61 // サーバースレッドの処理 62 @Override public void run() { 63 // サーバーが開始したのでEDT上でStopボタンをenableにする 64 SwingUtilities.invokeLater(() -> ui.btnStop.setEnabled(true)); 65 Socket serverSocket = ...; 66 serverSocket = setSoTimeout(1000); // 1秒でTimeoutにし、UIからのコマンドをチェック 67 LOOP: 68 for (;;) { 69 try { 70 // UIから指示があったらそれに従う 71 switch (pop()) { 72 case None: break; 73 case Stop: break LOOP; 74 ... 75 } 76 Socket sock = serverSocket.accept(); 77 // クライアントの相手をする 78 ... 79 } catch (SocketTimeoutException ex) { 80 // タイムアウトしたらまたループの最初から 81 } catch (InterruptedException ex) { 82 break LOOP; // accept実行中に割り込まれたら行儀よく終わる 83 } 84 } 85 ...後始末 86 // 再度開始できるようにEDT上でStartボタンをenableにする 87 SwingUtilities.invokeLater(() -> ui.btnStart.setEnabled(true)); 88 } 89}

投稿2016/10/10 08:17

編集2016/10/10 08:18
KSwordOfHaste

総合スコア18394

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

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

infologicmation

2016/10/10 11:58

自己解決しました。 ご協力ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問