这个基于 Apache 的 API 客户端 Class 线程安全吗?
Is this Apache based API Client Class Thread Safe?
这是一个非单例 class,用于将有效负载发送到 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方法会不会有问题?
我认为这很好,因为全局变量的 none 以任何方式被修改(它们是只读的,用于促进 API 调用)。
此外,jsonPayload 是一个局部变量,因此每个线程都会获得自己的版本,并且一个线程没有机会获取另一个线程的有效负载内容,对吗?
虽然在您提出的方法的问题范围之外存在多个问题(什么是 """
,您真的想手工制作 JSON 对象吗?不处理异常)您对并发性的评估似乎是正确的。
不过,您可能想要确保这一点,如果您的变量不应该被更改,也许可以将它们设为最终变量。这样,如果将来的代码修改确实导致它们被更改,您将在编译时知道存在错误。或者这可能不是一个错误,这些变量需要更改...但您会知道您必须重新审视并发问题。
是的,它是线程安全的。您正在尝试 post 某些东西到远程位置。看来你并不担心人们会覆盖远程位置的内容(如果你是那么即使线程安全逻辑也不会帮助你)
你的逻辑"I think it would be fine because none of the global variables are modified in any way (they are read only and used to facilitate the API call)."
是正确的。
出于可读性和约定目的,我建议使用带有属性的最终结构。
当线程以不受控制的方式使用和写入共享数据时,就会出现多线程问题。
含义:
- 当您的所有线程都仅调用发送方法时,您就没有问题 - 因为所有线程都在读取和使用相同的数据
- 但是当这些线程更改任何字段的内容时 - 那么所有的赌注都会被取消。
事实是:您的字段具有包可见性 - 这意味着从 "outside" 更新它们非常简单。如果字段内容更改,MyApiClient 的对象甚至通知。
因此:
- 首先,将这些字段设为私有,以便向外部隐藏此类详细信息
- 也考虑将它们定为最终版本
您可以使用基于 apache http api 构建的 http-request。文档 here.
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));
}
}
HTTP_REQUEST 是线程安全的
这是一个非单例 class,用于将有效负载发送到 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方法会不会有问题?
我认为这很好,因为全局变量的 none 以任何方式被修改(它们是只读的,用于促进 API 调用)。
此外,jsonPayload 是一个局部变量,因此每个线程都会获得自己的版本,并且一个线程没有机会获取另一个线程的有效负载内容,对吗?
虽然在您提出的方法的问题范围之外存在多个问题(什么是 """
,您真的想手工制作 JSON 对象吗?不处理异常)您对并发性的评估似乎是正确的。
不过,您可能想要确保这一点,如果您的变量不应该被更改,也许可以将它们设为最终变量。这样,如果将来的代码修改确实导致它们被更改,您将在编译时知道存在错误。或者这可能不是一个错误,这些变量需要更改...但您会知道您必须重新审视并发问题。
是的,它是线程安全的。您正在尝试 post 某些东西到远程位置。看来你并不担心人们会覆盖远程位置的内容(如果你是那么即使线程安全逻辑也不会帮助你)
你的逻辑"I think it would be fine because none of the global variables are modified in any way (they are read only and used to facilitate the API call)." 是正确的。
出于可读性和约定目的,我建议使用带有属性的最终结构。
当线程以不受控制的方式使用和写入共享数据时,就会出现多线程问题。
含义:
- 当您的所有线程都仅调用发送方法时,您就没有问题 - 因为所有线程都在读取和使用相同的数据
- 但是当这些线程更改任何字段的内容时 - 那么所有的赌注都会被取消。
事实是:您的字段具有包可见性 - 这意味着从 "outside" 更新它们非常简单。如果字段内容更改,MyApiClient 的对象甚至通知。
因此:
- 首先,将这些字段设为私有,以便向外部隐藏此类详细信息
- 也考虑将它们定为最终版本
您可以使用基于 apache http api 构建的 http-request。文档 here.
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));
}
}
HTTP_REQUEST 是线程安全的