如何捕获Java中setSoTimeout()触发的SocketTimeoutException
问题1:如何捕获特定的SocketTimeoutException
ExecutorService提交Callable任务后,任务内部抛出的所有异常都会被自动包装到ExecutionException中,你通过Future.get()捕获到的永远是外层的ExecutionException,真实的业务异常存放在它的cause属性中,按以下方式处理即可:
try { Future<String> connectionFuture = executorService.submit(waitForConnectionCallable); String connectionResult = connectionFuture.get(); } catch (InterruptedException e) { // 处理线程中断逻辑 Logs.error(TAG, "等待连接任务被中断"); e.printStackTrace(); } catch (ExecutionException e) { // 取出真实的业务异常 Throwable cause = e.getCause(); if (cause instanceof SocketTimeoutException) { // 单独处理连接超时逻辑 Logs.error(TAG, "连接等待超时,未收到客户端连接"); // 可在此处添加重试、资源释放等自定义逻辑 } else if (cause instanceof IOException) { // 处理其他IO异常 Logs.error(TAG, "IO异常,建立连接失败"); cause.printStackTrace(); } else { // 处理其他未知异常 Logs.error(TAG, "建立连接时发生未知错误"); cause.printStackTrace(); } }
另外你不需要在Callable的call()方法中单独声明抛出SocketTimeoutException,因为SocketTimeoutException本身就是IOException的子类,你已经声明的throws IOException已经完全覆盖了该异常。
问题2:为什么SocketTimeoutException没出现在setSoTimeout()的throws列表
你误解了文档描述的异常抛出主体:
setSoTimeout()本身的作用仅为设置Socket的超时参数,不会触发超时逻辑,所以它只会抛出参数非法、底层Socket错误类的异常,也就是文档标注的IllegalArgumentException和SocketException。- 文档中提到的
SocketTimeoutException,是后续调用accept()阻塞方法时才会抛出的异常,查看ServerSocket.accept()的方法签名就能看到它明确声明了抛出IOException,SocketTimeoutException属于IO异常的子类,完全符合签名要求。
内容的提问来源于stack exchange,提问作者Mahm00d
相关产品推荐
相关产品推荐

