Ваше приложение перестает отвечать, потому что оно не является многопоточным.Без многопоточности ваше приложение будет «остановлено» в тот момент, когда вы нажмете кнопку «ссылка», потому что вызов ServerSocket#accept
.
Причиной этого является блокировка природа метода accept
.Пока другой сокет не соединится, ServerSocket
ожидает и удерживает свой текущий поток "приостановленным".Думайте об этом как о внутреннем цикле while, подобном этому:
while(!isConnected())
{
// check if there is a new request
}
Представьте себе, что ни один клиент никогда не подключится.Как эта петля когда-нибудь остановится?Никогда.
Возможный обходной путь - это поточная обработка всей части пользовательского интерфейса или части «модели данных».
Мой предпочтительный способ - создать собственный класс, который обрабатывает только метод ServerSocket#accept
иделегирует входящие соединения другому потоку, который заботится обо всем остальном.Я делаю это для того, чтобы мой сервер был доступен в любое время, что может быть не лучшим решением для вашей проблемы.
Вот как обычно выглядит мой вспомогательный класс:
ClientAccepter.java:
public class ClientAccepter
implements Runnable
{
// the ServerSocket
private final ServerSocket server;
// ExecutorServices ease the pain of threading your application quite a lot
private final ExecutorService es = Executors.newCachedThreadPool();
private boolean isAlive = true;
public ClientAccepter( ServerSocket server )
{
this.server = server;
}
@Override
public void run()
{
//This is where you specify your desired behaviour.
//Example:
while ( isAlive )
{
try
{
es.execute( new ClientHandler( server.accept() ) );
}
catch ( IOException e )
{
e.printStackTrace();
}
}
}
}
Вызов такого класса может выглядеть следующим образом:
Server.java:
public class Server
{
//ExecutorServices are the best and easy to use.
private static ExecutorService serverThreader = Executors.newSingleThreadExecutor();
public static void main( String[] args )
{
try
{
serverThreader.execute( new ClientAccepter( new ServerSocket( 8080 ) ) );
}
catch ( IOException e )
{
e.printStackTrace();
//further exception handling.
}
}
}
Toчестно говоря, это может быть не лучшим подходом, но это мой предпочтительный способ обработки операций блокировки.Вам следует подумать о работе с orcale параллельным учебником и определенно взглянуть на ExecutorServices
, потому что они являются невероятной платформой для удобной обработки потоковых пулов.
Также специально для JavaFX существует руководство по параллелизму .