RestTemplate 스레드는 안전합니까?
봄인가요?RestTemplate
안전하다고요?그것은
- 아이사
RestTemplate
여러 연결이 안전하게 공유할 수 있는 Strategy 객체 또는 - 아이사
RestTemplate
사용 중에는 공유할 수 없고 각 연결에 대해 새로 만들기 또는 풀링이 필요한 연결 개체(예: 데이터베이스 연결)입니다.
RestTemplate
스레드 안전(emphasis 추가):
개념적으로, 그것은 매우 비슷합니다.
JdbcTemplate
,JmsTemplate
, 그리고 Spring Framework 및 기타 포트폴리오 프로젝트에서 볼 수 있는 다양한 템플릿을 제공합니다.예를 들어, 이는 일단 가 구성되면 스레드 세이프(thread safe)가 된다는 것을 의미합니다.
RestTemplate
class는 HTTP를 처리하기 위해 상태 정보를 변경하지 않습니다. class는 연결 개체와 같지 않고 Strategy 설계 패턴의 인스턴스입니다.상태 정보가 없는 상태에서 서로 다른 스레드가 서로 공유할 경우 상태 정보가 손상되거나 경주할 가능성이 없습니다.RestTemplate
물건. 스레드가 이러한 개체를 공유하는 것이 가능한 이유입니다.이것이 스레드가 이러한 개체를 공유하는 것이 가능한 이유입니다.
소스 코드를 검사하면 사용하지 않는 것을 알 수 있습니다.synchronized
메소드 또는volatile
객체의 시공 후 나사산 안전을 제공하기 위한 필드.따라서 a를 수정하는 것은 안전하지 않습니다.RestTemplate
시공 후의 물건 하는 것은 안전하지 않습니다.특히 메시지 변환기를 추가하는 것은 안전하지 않습니다.
메시지 변환기 목록을 제공하려면 다음 중 하나를 수행해야 합니다.
- 을 합니다.
RestTemplate(List<HttpMessageConverter<?>> messageConverters)
시공자의 내부 목록으로서messageConverters
이다.final
, 메시지 변환기 목록을 안전하게 게시합니다. - 을 합니다.
setMessageConverters(List<HttpMessageConverter<?>> messageConverters)
돌연변이체를 제거한 다음 안전하게 변경된 부분을 publish합니다.RestTemplate
물건.다음을 포함하는 스프링 빈 정의를 사용합니다.<property name="messageConverters"><list>...
대부분의 실용적인 사용 사례에서 용기를 설정하는 스레드에 의해 콩이 안전하게 게시되기 때문에 이렇게 합니다. - 사용하다
List.add
에 의해 반환된 참조로getMessageConverters()
그런 다음 변경된 내용을 안전하게 게시합니다.RestTemplate
물건.그러나 다음에 대한 문서.RestTemplate
는 메시지 변환기 목록을 변경하는 데 사용할 수 있는 참조를 반환한다고 명시적으로 명시하지 않습니다.현재 구현은 가능하지만, 가능한 경우 구현이 A를 반환하도록 변경될 수도 있습니다.Collections.unmodifiableList
아니면 목록의 복사본.그래서 이런 식으로 변경하지 않는 것이 더 나을 수 있습니다.
첫 번째 경우는 개체를 구성할 때 메시지 변환기를 설정할 수 있는 유일한 수단이므로 "구성되면 스레드 안전"이라고 말하는 것이 정확합니다.
클래스는 Spring Framework의 일부이므로 거의 모든 실제적인 경우 클래스의 개체는 첫 번째(컨스트럭터를 사용한 종속성 주입) 또는 두 번째(세터를 사용한 종속성 주입) 메서드를 사용하여 Spring Application Context의 일부로 설정되므로 여러 스레드에 안전하게 게시될 수 있습니다.
도서관 입장에서는 실이 안전합니다.예를 들어 getMessageConverters()는 공개적입니다. 즉, 누군가 목록을 잡고 라이브러리의 목적을 벗어나 수정하면 문제가 발생합니다(그리고 심지어 setter 메서드도 RestTemplate 인스턴스화 후 언제든지 호출되면 - 그리고 다른 스레드에서 사용하는 동안 boom!).아마 로스에게 일어난 일일 겁니다. (답변을 하기에는 평판이 충분하지 않지만, 저는 안전한 논쟁과 안전하지 않은 논쟁을 모두 지지합니다.)
좋아요, 이런 문제를 일으킨 소스 제어에서 예전 코드를 찾아낼 수는 있겠지만요.
생성 시 동기화하더라도 다른 스레드가 내부 컬렉션을 수정할 수 있는 상황이 존재한다고 보는 것이 타당할 것 같습니다.그러니까 조심하는 게 좋을 거예요.예전 코드를 보면 네, 실제로는 메시지 변환기를 사용하고 있었습니다.하지만 창작에 동기화될 때만 가능합니다.
restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
그 후 RestTemplate와의 상호작용은 다음과 같습니다.
return restTemplate.postForObject(url, object, clazz);
이것은 또한 결국 예외를 던지는 선이 됩니다.
물론 메시지 변환기와의 상호 작용은 없습니다. (메시지 변환기에 대한 로컬 참조는 없습니다.)
스택 트레이스와 스프링 소스 코드를 살펴보면 다음 라인에서 오류가 발생했습니다.
for (HttpMessageConverter<?> converter : getMessageConverters()) {
그래서 우리는 무엇을 가지고 있습니까?
- Converters 메시지에 동시에 액세스할 수 있습니다.
- 만약 우리 코드가 하지 않았다면, 어떤 코드가 하지 않았을까요?나는 답을 모른다.이 앱에서 성능은 문제가 되지 않았기 때문에 그때마다 새로운 RestTemplate를 만드는 것이 제 해결책이었습니다.
따라서 요약하자면, 메시지 변환기를 직접 가지고 장난을 친다면 사물이 안전하지 않을 수도 있습니다.이번 건은 이상한 사건이지만, 출판하는 것이 유용할 것이라고 생각했습니다.
위의 승인된 답변에 동의하지 않는 것은 싫지만(강조), 아니요, 스레드가 안전하지 않습니다.창작 후에도.내부적으로 ArrayLists를 가지고 장난을 치고 있지만 소스에 대해서는 자세히 조사하지 않았습니다.저는 이런 것들을 너무 많이 봤습니다.
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at org.springframework.web.client.RestTemplate$AcceptHeaderRequestCallback.doWithRequest(RestTemplate.java:677)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:567)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:545)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:253)
언급URL : https://stackoverflow.com/questions/22989500/is-resttemplate-thread-safe
'programing' 카테고리의 다른 글
Oracle 10g : XML에서 데이터 추출(select)(CLOB Type) (0) | 2023.10.29 |
---|---|
wocommerce 웹 후크가 발사되지 않음 (0) | 2023.10.29 |
StackOverflow와 같은 "토스트" 메시지 생성 (0) | 2023.10.24 |
단일 쿼리로 mysql 테이블에서 모든 부모 찾기(Recursive Query) (0) | 2023.10.24 |
DBMS Profiler를 사용한 PL/SQL 커버리지 보고서 구축 (0) | 2023.10.24 |