stop()
サーバーを閉じるメソッドを持つクライアントを受け入れるサーバーがあり、java.nio.AsynchronousCloseException
解決したい問題が発生しています。メソッドは別のstop()
スレッドで呼び出されます。これが競合状態の原因だと思います。
これが私のコードです:
public void run() {
InetSocketAddress addr = new InetSocketAddress(provider.getConnection(), 12354);
try {
server = ServerSocketChannel.open();
server.configureBlocking(true);
server.socket().bind(addr);
parent.setIP(addr.getAddress().getHostAddress().toString());
password = generatePassword();
parent.setPassword(password);
parent.setStatus("Ready.");
} catch (IOException e) {
parent.die("Could not start server: " + e.getMessage());
runner = null;
}
while (runner == Thread.currentThread()) {
try {
SocketChannel sc = server.accept();
if (available) {
session = new ReceiveSession(this, sc, password, addr.getAddress());
session.start();
available = false;
} else {
new ReceiveBusyHandler(sc).start();
}
} catch (IOException e) {
synchronized (swallowException) {
if (!swallowException) {
parent.showError(e.toString());
}
available = true;
}
}
}
}
public void stop() throws IOException {
synchronized (swallowException) {
swallowException = true;
runner = null;
if (server != null) {
server.socket().close();
server.close();
}
swallowException = false;
System.out.println("Server down");
}
}
(参考までに、同期を試みswallowException
たBoolean
ことがわかります。)
サーバーループの例外ハンドラーがアクセスする前に、stop()
メソッドが設定swallowException
されtrue
てから元に戻っているようです。false
更新:Object
ロックとして使用する新しいものを導入しwait()/notify()
、問題を修正するために使用しました:
public void run() {
InetSocketAddress addr = new InetSocketAddress(provider.getConnection(), 12354);
try {
server = ServerSocketChannel.open();
server.configureBlocking(true);
server.socket().bind(addr);
parent.setIP(addr.getAddress().getHostAddress().toString());
password = generatePassword();
parent.setPassword(password);
parent.setStatus("Ready.");
} catch (IOException e) {
parent.die("Could not start server: " + e.getMessage());
runner = null;
}
while (runner == Thread.currentThread()) {
try {
SocketChannel sc = server.accept();
if (available) {
session = new ReceiveSession(this, sc, password, addr.getAddress());
session.start();
available = false;
} else {
new ReceiveBusyHandler(sc).start();
}
} catch (IOException e) {
synchronized (lock) {
if (!swallowException) {
parent.showError(e.toString());
}
lock.notify();
available = true;
}
}
}
}
public void stop() throws IOException {
synchronized (lock) {
swallowException = true;
runner = null;
if (server != null) {
server.socket().close();
server.close();
}
while (swallowException) {
try {
lock.wait();
swallowException = false;
} catch (InterruptedException e) {
}
}
//swallowException = false;
System.out.println("Server down");
}
}