首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >重用javax.ws.rs.client.Client

重用javax.ws.rs.client.Client
EN

Stack Overflow用户
提问于 2018-02-19 09:24:40
回答 1查看 1.2K关注 0票数 2

我刚刚对我的代码运行了一个分析器,我注意到我花费了大量的时间使用ClientBuilder.newClient()创建新的客户机。这并不令人惊讶,因为文档指出,这是一个繁重的操作,如果可能的话,您应该重用客户机。

所以我创建了一个简单的资源库来管理我所有的客户

代码语言:javascript
复制
public class SimpleClientResourcePool implements ResourcePool<Client> {
    private LinkedList<Client> pool = new LinkedList<>();

    @Override
    public Optional get() {
        if(pool.isEmpty())
            return Optional.empty();
        return Optional.of(pool.getFirst());
    }

    @Override
    public void release(Client value) {
        pool.addLast(value);
    }
}

我就这样用它

代码语言:javascript
复制
    Client client = clientResourcePool.get().orElseGet(ClientBuilder::newClient);
    Response response = get(countryId, uri, client);

    try {
      ///random code
    } finally {
        response.close();
        clientResourcePool.release(client);
    }

当我作为用户在本地运行时,我没有看到任何问题,但是在加载过程中,似乎存在一个并发问题,我对此不太了解。

我得到了一个似乎基于此错误的异常:

代码语言:javascript
复制
Caused by: java.lang.IllegalStateException: Connection is still allocated
        at org.apache.http.util.Asserts.check(Asserts.java:34)
        at org.apache.http.impl.conn.BasicHttpClientConnectionManager.getConnection(BasicHttpClientConnectionManager.java:266)
        at org.apache.http.impl.conn.BasicHttpClientConnectionManager$1.get(BasicHttpClientConnectionManager.java:217)
        at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:190)
        at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
        at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
        at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
        at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
        at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:313)

那么,这不是您应该重用客户端的方式吗?还是我遗漏了一些显而易见的东西?

关闭客户似乎只会导致其他例外..。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-19 10:28:48

是的,您所经历的问题肯定与您的池实现有关。实际上,我在代码中至少看到了3个问题:

  1. SimpleClientResourcePool不是线程安全的。对pool集合的访问不同步。在您的例子中,Queue也会比LinkedList更好,所以看看并发包提供的ConcurrentLinkedQueue
  2. 您应该从池中提取Client对象,或者根据您的需要将它移动到另一个“用过的客户端”集合,然后再调用release
  3. 始终在一行if语句附近执行{}操作。。如果您的团队中有人在" if“中添加了另一行,那么在自动合并之后,代码将不会编译。

应用这样的建议,你可以从这样的事情开始:

代码语言:javascript
复制
public class SimpleClientResourcePool implements ResourcePool<Client> {
    private final Queue<Client> pool = new ConcurrentLinkedQueue<>();

    @Override
    public Optional get() {
        return Optional.ofNullable(pool.poll());
    }

    @Override
    public void release(Client value) {
        pool.offer(value);
    }
}

希望能帮上忙!

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48862912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档