내 Java 클라이언트의 동기식 및 비동기식 메서드가 필요한 프로젝트에서 작업 중입니다. 일부 고객은 동기식을 호출하고 일부 고객은 거기에 따라 Java 클라이언트의 비동기식 메소드를 호출합니다. 호출 인터페이스를 구현하는 내 ClientTask
클래스이고 나는 ClientTask class
에서 DI 패턴을 사용하여 종속성 주위를 통과하고 지금 아래멀티 스레딩 환경에서 빌더 패턴 스레드를 안전하게 만드는 방법은 무엇입니까?
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;
}
}
그리고 -
다음은 synchronous
및 asynchronous
방법을 가지고 내 자바 클라이언트입니다. 통화 방법, 난 그냥 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
클래스 고객이 입력 매개 변수를 만들기 위해 사용 빌더 후두둑를 사용하면 TestingClient
에 전달 - 나는 multithrea에서 ClientTask
클래스 ClientKey
변수를 사용하고 같은
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
변수를 변경하려고하면 어떤 일이 발생할지 확실하지 않음 -
고객이 아래 코드를 사용하여 전화를 걸고 우리를 호출 할 수 있습니다. 뿐만 아니라이 멀티 스레드 응용 프로그램 -
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
클래스에 여러 값을 전달할 수있는 내 위의 코드가 안전 여부를 스레드할지 여부를 이해하려고 노력. 때문에 내
ClientKey
클래스가 스레드로부터 안전하지 않지만 확실하지 않은 느낌이 들었습니다.
여기에 StringBuffer
이 필요하거나 StringBuilder
은 괜찮습니다. 동기화되지 않았기 때문에 StringBuilder가 StringBuffer보다 빠르기 때문에 괜찮습니다.
아무도 도와 줄 수 있습니까?
ClientKey에 할당 된 후에 parameterMap을 수정할 수 없도록하려면, 다음과 같이해야합니다 :'this.parameterMap = Collections.unmodifiableMap (new HashMap (builder.parameterMap)) '하지만 여러 스레드가 현재 동기화되지 않은 LinkedHashMap에 액세스하는 경우 이미 ClientKey 외부의 코드에 문제가 있습니다. –
Erwin 제안에 감사드립니다. 고객이 다른 스레드에서 'TestingClient' 클래스로 다른 값을 전달할 수 있습니다. 즉, ClientId 클래스를 사용하여 userId가 전달하는 각 호출에 대해 계속해서 입력 매개 변수를 작성해야합니다. ParameterMap에서도 마찬가지입니다. 그리고 LinkedHashMap 코드는 고객이 애플리케이션에서 우리에게 어떻게 전화를 걸지를 보여주는 예입니다. 그들은 그 곳에서 ConcurrentHashMap을 가질 수 있습니다. 우리에게 전화하는 방법을 코드화합니다 .. –