gpt4 book ai didi

java - 如何在多线程环境中使构建器模式线程安全?

转载 作者:行者123 更新时间:2023-12-01 13:34:55 25 4
gpt4 key购买 nike

我正在开发一个项目,其中我需要 Java 客户端的同步和异步方法。有些客户会调用同步方法,有些客户会根据需求调用我的java客户端的异步方法。

下面是我的 java 客户端,它具有同步异步方法 -

public class TestingClient implements IClient {

private ExecutorService service = Executors.newFixedThreadPool(10);
private RestTemplate restTemplate = new RestTemplate();

// for synchronous
@Override
public String executeSync(ClientKey keys) {

String response = null;
try {

Future<String> handle = executeAsync(keys);
response = handle.get(keys.getTimeout(), TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {

} catch (Exception e) {

}

return response;
}

// for asynchronous
@Override
public Future<String> executeAsync(ClientKey keys) {

Future<String> future = null;

try {
ClientTask ClientTask = new ClientTask(keys, restTemplate);
future = service.submit(ClientTask);
} catch (Exception ex) {

}

return future;
}
}

现在下面是我的 ClientTask 类,它实现了 Callable 接口(interface),我在 ClientTask 类 中使用 DI 模式传递依赖项。在调用方法中,我只是在 machineIPAddress 上创建一个 URL,并使用传递给 ClientTask 类的 ClientKeys ,然后访问服务器使用 RestTemplate 并获取响应 -

class ClientTask implements Callable<String> {

private ClientKey cKeys;
private RestTemplate restTemplate;

public ClientTask(ClientKey cKeys, RestTemplate restTemplate) {
this.restTemplate = restTemplate;
this.cKeys = cKeys;
}

@Override
public String call() throws Exception {

// .. some code here
String url = generateURL("machineIPAddress");
String response = restTemplate.getForObject(url, String.class);

return response;
}

// is this method thread safe and the way I am using `cKeys` variable here is also thread safe?
private String generateURL(final String hostIPAdress) throws Exception {
StringBuffer url = new StringBuffer();
url.append("http://" + hostIPAdress + ":8087/user?user_id=" + cKeys.getUserId() + "&client_id="
+ cKeys.getClientId());

final Map<String, String> paramMap = cKeys.getParameterMap();
Set<Entry<String, String>> params = paramMap.entrySet();
for (Entry<String, String> e : params) {
url.append("&" + e.getKey());
url.append("=" + e.getValue());
}

return url.toString();
}
}

下面是我的 ClientKey 类,使用 Builder 模式,客户将使用该类将输入参数传递给 TestingClient -

public final class ClientKey {

private final long userId;
private final int clientId;
private final long timeout;
private final boolean testFlag;
private final Map<String, String> parameterMap;

private ClientKey(Builder builder) {
this.userId = builder.userId;
this.clientId = builder.clientId;
this.remoteFlag = builder.remoteFlag;
this.testFlag = builder.testFlag;
this.parameterMap = builder.parameterMap;
this.timeout = builder.timeout;
}

public static class Builder {
protected final long userId;
protected final int clientId;
protected long timeout = 200L;
protected boolean remoteFlag = false;
protected boolean testFlag = true;
protected Map<String, String> parameterMap;

public Builder(long userId, int clientId) {
this.userId = userId;
this.clientId = clientId;
}

public Builder parameterMap(Map<String, String> parameterMap) {
this.parameterMap = parameterMap;
return this;
}

public Builder remoteFlag(boolean remoteFlag) {
this.remoteFlag = remoteFlag;
return this;
}

public Builder testFlag(boolean testFlag) {
this.testFlag = testFlag;
return this;
}

public Builder addTimeout(long timeout) {
this.timeout = timeout;
return this;
}

public ClientKey build() {
return new ClientKey(this);
}
}

public long getUserId() {
return userId;
}

public int getClientId() {
return clientId;
}

public long getTimeout() {
return timeout;
}

public Map<String, String> getParameterMap() {
return parameterMap;

public boolean istestFlag() {
return testFlag;
}
}

我上面的代码线程安全吗,因为我在多线程环境中的 ClientTask 类中使用 ClientKey 变量,所以不确定如果另一个线程尝试创建 会发生什么调用 TestingClient 同步方法时的 ClientKey 变量 -

因为客户将使用以下代码调用我们,他们也可以从那里调用我们多线程应用程序 -

IClient testClient = ClientFactory.getInstance();

Map<String, String> testMap = new LinkedHashMap<String, String>();
testMap.put("hello", "world");

ClientKey keys = new ClientKey.Builder(12345L, 200).addTimeout(2000L).parameterMap(testMap).build();

String response = testClient.executeSync(keys);

因此,只是想了解我的上述代码是否是线程安全的,因为它们可以从多个线程将多个值传递给我的 TestingClient 类。我有一种感觉,由于 parameterMap,我的 ClientKey 类不是线程安全的,但不确定。

我还需要 StringBuffer 这里还是 StringBuilder 就可以了,因为 StringBuilder 比 StringBuffer 更快,因为它不同步。

谁能帮我解决这个问题吗?

最佳答案

参数ClientKey key已给出,所以我假设总是不同的。

我没有发现您的代码有任何同步问题,我将解释一下:

ClientTask ClientTask = new ClientTask(keys, restTemplate);
future = service.submit(ClientTask);
  • 从方法内部创建一个 ClientTask 对象,该对象不在线程之间共享。
  • 使用 service.submit,返回一个 Future 对象
  • ClientTask 对象仅在 generateURL 方法内读取 key ,但是,正如我之前所说,ClientKeys 对象作为参数,所以只要这个对象不被共享就可以了。

总之,代码的线程安全性取决于 ExecutorServiceFuture 的线程安全性。

更新:澄清只要该对象不被共享

ClientKeys keys;
add keys to @keys
.. code
executeAsync(.., keys)
... code
add keys to @keys
add keys to @keys
executeAsync(.., keys)
executeAsync(.., keys)
add keys to @keys
... code
add keys to @keys
executeAsync(.., keys)

这(或多或少)就是我的意思是分享。由于调用了executeAsync(),keys 正在多个线程中使用。在这种情况下,一些线程正在读取,而其他线程正在向其写入数据,从而导致通常称为的race condition .

更新 2:StringBuffer 对象是 generateURL 的本地对象(也称为其范围内),无需同步它。

关于java - 如何在多线程环境中使构建器模式线程安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21359770/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com