OkHttpClient的最佳实践优化方案

废话不多说,直接上代码

java 复制代码
public class OkHttpExample {


    // 同步 GET 请求
    private static void syncGet(String url) {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(3, TimeUnit.SECONDS)
                .readTimeout(3, TimeUnit.SECONDS)
                .build();
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Accept", "application/json")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                System.out.println("GET 成功: " + response.body().string());
            } else {
                System.err.println("GET 失败: HTTP " + response.code());
            }
        } catch (IOException e) {
            System.err.println("网络异常: " + e.getMessage());
        }
    }

   
}

这样存在一个问题,不停地实例化OkHttpClient,这样会浪费资源,且在高并发下,会存在性能隐患。所以,以上代码可以优化为下面这样子

java 复制代码
public class OkHttpExample {

    private static final OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(3, TimeUnit.SECONDS)
            .readTimeout(3, TimeUnit.SECONDS)
            .build();

    // GET 请求
    private static void syncGet(String url) {
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Accept", "application/json")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                System.out.println("GET 成功: " + response.body().string());
            } else {
                System.err.println("GET 失败: HTTP " + response.code());
            }
        } catch (IOException e) {
            System.err.println("网络异常: " + e.getMessage());
        }
    }

   
}

这样是不是没有优化空间了呢?看源码后,其实还有进一步代码空间,就okhttp3.ConnectionPool,这个就是连接池,这也就是不建议重复实例化OkHttpClient原因之一。

java 复制代码
public ConnectionPool() {
    this(5, 5, TimeUnit.MINUTES);
}

默认是设置5,对于绝大部分场景已经够用了,但如果还想进一步优化,可以修改成这样

java 复制代码
public class OkHttpExample {

    private static final OkHttpClient client = new OkHttpClient.Builder()
            .connectionPool(new ConnectionPool(20, 60, TimeUnit.SECONDS))
            .connectTimeout(3, TimeUnit.SECONDS)
            .readTimeout(3, TimeUnit.SECONDS)
            .build();

    // 同步 GET 请求
    private static void syncGet(String url) {
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Accept", "application/json")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                System.out.println("GET 成功: " + response.body().string());
            } else {
                System.err.println("GET 失败: HTTP " + response.code());
            }
        } catch (IOException e) {
            System.err.println("网络异常: " + e.getMessage());
        }
    }

   
}

若调用方是消息消费者/定时任务,推荐异步 enqueue(),但需确保回调中不阻塞,这种在安卓开发常使用。这个是通过okhttp3.Dispatcher实现,这个也可以进行调整。

java 复制代码
 OkHttpClient client = new OkHttpClient.Builder()
    .dispatcher(new Dispatcher().apply(d -> {
        d.setMaxRequests(128); // 全局最大并发(默认64)
        d.setMaxRequestsPerHost(12);// 单域名最大并发(默认5)
    }))
    .build();   
java 复制代码
    // 异步 GET 请求(推荐用于 Android/UI 线程)
    private static void asyncGet(String url) {
        Request request = new Request.Builder()
                .url(url)
                .build();

        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                System.err.println("异步请求失败: " + e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                // 注意:回调线程非主线程,Android 中更新 UI 需切回主线程
                try (Response res = response) { // 手动关闭,避免泄漏
                    if (res.isSuccessful()) {
                        System.out.println("异步 GET 成功: " + res.body().string());
                    } else {
                        System.err.println("异步响应异常: " + res.code());
                    }
                }
            }
        });
    }
相关推荐
淘源码d1 小时前
医学影像云PACS系统——PACS诊断工作站
java·源码·影像处理·医院管理系统·影像工作站·云pacs系统·dicom 标准通信
心中有国也有家1 小时前
AtomGit Flutter 鸿蒙客户端:情绪日记的时间线实现
学习·flutter·华为·harmonyos
NiceCloud喜云2 小时前
Anthropic 一周三连发:Cowork 多端、Fable 5 按需付费、J-space 论文的技术解读
java·服务器·网络·人工智能·ai
SamDeepThinking2 小时前
组合还是继承?我在项目里主要看这两个判断
java·后端·面试
momo2 小时前
JAVA基础知识
java·开发语言
百里香酚兰2 小时前
【python学习笔记】pyttsx3库疑似只播报一次语音
笔记·python·学习
恣逍信点2 小时前
《凌微经》助读:本体论根基——“无之自悖”与“形性一体”
人工智能·科技·学习·程序人生·生活·交友·哲学
就叫_这个吧3 小时前
Activiti7工作流入门+案例应用
java·activiti7·工作流
Z_W_H_3 小时前
minikube start --driver=docker --memory=4000mb出现PROVIDER_DOCKER_NEWGRP
java·docker·minikube
折哥的程序人生 · 物流技术专研3 小时前
第3篇:手写促销策略引擎(满减、打折、立减)
java·设计模式·策略模式·开闭原则·编程实战·扩充系列·促销引擎