Java 这个基于Apache的API客户端类是线程安全的吗?

Java 这个基于Apache的API客户端类是线程安全的吗?,java,multithreading,concurrency,apache-httpclient-4.x,Java,Multithreading,Concurrency,Apache Httpclient 4.x,这是一个非单例类,用于向API发送有效负载 class MyApiClient { String url = "http://www.yankeeService.com" int playerId = 99 String playerFirstName = "Aaron" String playerLastName = "Judge" public void sendPayload(String content) { CloseableHttpClient cl

这是一个非单例类,用于向API发送有效负载

class MyApiClient {

  String url = "http://www.yankeeService.com"
  int playerId = 99
  String playerFirstName = "Aaron"
  String playerLastName = "Judge"

  public void sendPayload(String content) {

    CloseableHttpClient client = HttpClients.createDefault();
    HttpPost httpPost = new HttpPost();

    String jsonPayload = """ "{"id":"$playerId","name":"$playerLastName","dailyReport":"$content"}" """ ;
    StringEntity entity = new StringEntity(jsonPayload);
    httpPost.setEntity(entity);

    CloseableHttpResponse response = client.execute(httpPost);
    assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
    client.close();

 }

}
如果有多个线程进入sendPayload方法,会有任何问题吗

我认为这很好,因为没有任何全局变量以任何方式被修改(它们是只读的,用于促进API调用)


另外,jsonPayload是一个局部变量,因此每个线程都将获得其自己的版本,并且一个线程没有机会获取另一个线程的有效负载内容,对吗?

,而您提出的方法存在多个问题(什么是
”)“
,您真的想手工制作JSON对象,并且不处理异常吗)您对并发性的评估似乎是正确的


不过,您可能希望确保这一点,如果您的变量不应该被更改,那么可以将其设置为最终变量。这样,如果将来的代码修改确实导致它们被更改,您将在编译时知道存在错误。或者这不是一个错误,这些变量需要改变。。。但您将知道必须重新考虑并发问题。

是的,它是线程安全的。您正在尝试将某些内容发布到远程位置。似乎您并不担心人们在远程位置覆盖内容(如果您担心,那么即使线程安全逻辑也不会帮您)

您的逻辑“我认为这很好,因为没有任何全局变量以任何方式被修改(它们是只读的,用于促进API调用)。” 这是正确的


出于可读性和约定目的,我建议使用带有属性的最终构造。

当线程以不受控制的方式使用写入共享数据时,就会出现多线程问题

意思是:

  • 当所有线程都调用send方法时,您就不会有问题,因为所有线程都在读取和使用相同的数据
  • 但是,当这些线程更改任何字段的内容时,所有赌注都被取消
问题是:您的字段具有包可见性——这意味着从“外部”更新它们非常简单。MyApiClient的对象甚至不会注意到字段内容是否更改

因此:

  • 首先,将这些字段设置为私有,以便从外部隐藏此类详细信息
  • 考虑让它们成为最终版本

您可以使用构建在apache http api上的http请求。文件

类MyApiClient{
私有静态最终HttpRequest HTTP\u请求=
HttpRequestBuilder.createGet(“http://www.yankeeService.com")
.addContentType(ContentType.APPLICATION_JSON)
.build();
int playerId=99
弦乐演奏者firstname=“亚伦”
字符串播放器lastname=“Judge”
公共无效发送有效负载(字符串内容){
字符串jsonPayload=“”{“id”:“$playerId”,“name”:“$playerLastName”,“DailReport”:“$content”}”;
断言(HTTP_REQUEST.executeWithBody(jsonPayload.getStatusCode(),equalTo(200));
}
}

HTTP_请求是线程安全的

如何声明方法
已同步
?除了声明vars
final
(这是我喜欢的方法)之外,这还有什么作用吗?还有什么是
HttpClients.createDefault()
在后续调用中返回相同的对象,它使用以前调用中的缓存数据?
synchronized
将添加额外的保护层,但是你没有使它成为线程安全的——你只是使它成为单线程的——尽管所有单线程的东西都是线程安全的,但是它们不能扩展。既然已经是线程安全的,为什么还要将自己限制在一个同步的代码块上呢?如果要使用synchronized,不要在方法上同步,而是在私有对象上同步。同步该方法会导致使用对象的监视器,并可能导致饥饿。@两栖和
HttpClients.createDefault()
将创建一个新实例,这就是它专门使用create的原因。它是线程安全的。这实际上是从Groovy代码中提取的,这就是为什么JSON负载是这样创建的,以防有人怀疑。
class MyApiClient {
    private static final HttpRequest<?> HTTP_REQUEST =
            HttpRequestBuilder.createGet("http://www.yankeeService.com")
                    .addContentType(ContentType.APPLICATION_JSON)
                    .build();

    int playerId = 99
    String playerFirstName = "Aaron"
    String playerLastName = "Judge"

    public void sendPayload(String content) {

        String jsonPayload = """ "{"id":"$playerId","name":"$playerLastName","dailyReport":"$content"}" """ ;
        assertThat(HTTP_REQUEST.executeWithBody(jsonPayload).getStatusCode(), equalTo(200));

    }
}