Java 如何在多线程环境中使生成器模式线程安全?
我正在从事一个项目,在这个项目中,我需要java客户机的同步和异步方法。一些客户将调用我的java客户机的同步方法,一些客户将根据需要调用异步方法 下面是我的java客户端,它有Java 如何在多线程环境中使生成器模式线程安全?,java,multithreading,thread-safety,builder,Java,Multithreading,Thread Safety,Builder,我正在从事一个项目,在这个项目中,我需要java客户机的同步和异步方法。一些客户将调用我的java客户机的同步方法,一些客户将根据需要调用异步方法 下面是我的java客户端,它有同步和异步方法- public class TestingClient implements IClient { private ExecutorService service = Executors.newFixedThreadPool(10); private RestTemplate restTe
同步
和异步
方法-
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;
}
}
下面是我的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;
}
}
因此,请尝试了解我上面的代码是否是线程安全的,因为它们可以从多个线程向我的TestingClient
类传递多个值。我感觉我的ClientKey
类不是线程安全的,因为parameterMap
但不确定
我也需要StringBuffer
这里还是StringBuilder
就可以了,因为StringBuilder比StringBuffer快,因为它不同步。
有人能帮我吗?参数
ClientKey-keys
是给定的,所以我假设总是不同的
我认为您的代码没有任何同步问题,我将解释:
ClientTask ClientTask = new ClientTask(keys, restTemplate);
future = service.submit(ClientTask);
- 从方法内部创建一个
对象,该对象不在线程之间共享ClientTask
- 使用
,返回未来的对象service.submit
对象只读取方法ClientTask
中的键,但是,正如我前面所说的,generateURL
对象是作为一个参数给出的,所以只要不共享这个对象,就可以了ClientKeys
ExecutorService
和Future
是否是线程安全的
更新:只要未共享此对象,的说明
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(),代码>键
正在多个线程中使用。在这种情况下,一些线程正在读取键
,而另一些线程正在向其中写入数据,这导致了通常称为
更新2:StringBuffer
对象是本地对象(aka在generateURL
的范围内),不需要对其进行同步。如果要确保在分配给ClientKey后无法修改parameterMap,需要执行以下操作:this.parameterMap=Collections.unmodifiableMap(新HashMap(建筑商参数地图)
但是,如果当前有多个线程正在访问一个未同步的LinkedHashMap,则您的ClientKey外部代码中已经有问题。感谢Erwin的建议。客户可以将不同线程中的不同值传递给TestingClient
类,这意味着他们需要使用ClientKey
类进行输入参数always as userId会在每次调用时不断更改,ParameterMap也会更改。LinkedHashMap
code就是一个示例,客户会从那里调用我们的应用程序。他们可以在那里使用ConcurrentHashMap,因为它会为他们如何调用我们编码。。感谢ichramm的建议n、 只要这个对象没有被共享,当人们说时,我总是感到困惑。
这实际上意味着什么?因为每次调用的Clientkey键都会不同。所以在我的场景中,你看到这会发生吗?根据你写的关于你客户的内容和最后一个代码块,不,我认为不会发生。我明白了。还有我在这里需要StringBuffer吗?或者StringBuilder在我的generateURL
方法中也可以,因为StringBuilder比StringBuffer快,因为它不同步。StringBuffer
对象是本地对象(aka在generateURL
的范围内),不需要同步它。
ClientTask ClientTask = new ClientTask(keys, restTemplate);
future = service.submit(ClientTask);
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)