点击JButton三次后Swing GUI冻结 调用CoinMarketCap API场景问题求助
问题原因
- 阻塞Swing事件调度线程(EDT):Swing的所有UI交互、界面绘制逻辑都运行在唯一的EDT线程中,你直接在按钮的
ActionListener回调中执行同步HTTP请求这类阻塞耗时操作,会占用EDT线程导致界面无法响应用户操作、无法重绘,表现为冻结。 - HttpClient默认连接数限制:你使用的Apache HttpClient默认配置下,单个目标域名的最大并发连接数为2,累计发起3次请求到CoinMarketCap接口时,第三个请求无法获取到空闲连接,会进入无限阻塞等待,直接触发界面冻结。
修复方案
1. 调整HttpClient连接池配置
先修改HttpClient的初始化逻辑,提高最大连接数上限,避免连接不足导致的阻塞:
// 把原来的client初始化替换为如下配置 private static final HttpClient client = HttpClientBuilder.create() .setMaxConnTotal(20) // 总最大连接数 .setMaxConnPerRoute(10) // 单个域名最大连接数,满足多次调用的需求 .build();
2. 将API调用移到后台线程执行
Swing官方推荐使用SwingWorker处理后台耗时任务,既不会阻塞EDT,任务执行完成后也能安全更新UI:
修改按钮的点击事件逻辑,把testCallingAPI()放到SwingWorker中运行:
viewInfoButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 可选:点击后先禁用按钮,防止重复发起请求 viewInfoButton.setEnabled(false); new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { // 后台线程执行耗时的API调用,不会阻塞EDT testCallingAPI(); return null; } @Override protected void done() { // 任务执行完成后回到EDT线程,可以在这里更新UI viewInfoButton.setEnabled(true); // 如果要把接口返回的内容展示到界面上,也在这里操作 } }.execute(); } });
额外优化建议
- 可以给HTTP请求加上超时时间,避免接口无响应时长时间阻塞后台线程:
RequestConfig requestConfig = RequestConfig.custom() .setConnectTimeout(5000) // 连接超时5秒 .setSocketTimeout(10000) // 读取超时10秒 .build(); HttpGet get = new HttpGet(userBuild.build()); get.setConfig(requestConfig);
- 每次调用接口后及时关闭
HttpGet、BufferedReader等资源,避免资源泄漏。
内容的提问来源于stack exchange,提问作者CompSydBoi
相关产品推荐
相关产品推荐

