Java EE 컨테이너에서 스레드 생성이 권장되지 않는 이유는 무엇입니까?


120

Java EE 개발에 대해 처음으로 배운 것 중 하나는 Java EE 컨테이너 내부에 자체 스레드를 생성해서는 안된다는 것입니다. 근데 생각 해보니 그 이유를 모르겠어요.

낙담 한 이유를 명확하게 설명 할 수 있습니까?

대부분의 엔터프라이즈 응용 프로그램에는 메일 데몬, 유휴 세션, 정리 작업 등과 같은 일종의 비동기 작업이 필요합니다.

그렇다면 실제로 스레드를 생성하지 않아야한다면 필요할 때 올바른 방법은 무엇입니까?


4
비동기 작업은 일반적으로 JMS 메시징 및 MDB를 사용하여 수행됩니다.
Ken Liu

5
JSR 236 이 컨테이너에 구현 되면이 문제는 곧 과거의 일이 될 것입니다 .
letmaik 2013-08-04

5
그것은 어떤 두 번째 스레드가 생성되고 컨테이너에 의해 관리되어야하기 때문에 스레드가 다른 기업 리소스에 액세스 할 수 있습니다 그래서 낙담. Java EE7에는 엔터프라이즈 환경에서 스레드를 작성하는 표준적이고 올바른 방법이 있습니다. Concurrency Utils를 사용하면 컨테이너에서 새 스레드를 만들고 관리하여 모든 EE 서비스를 사용할 수 있습니다. 예 여기에
크리스 리치

JSF / EJB 관점에서 몇 가지 올바른 방법은 다음에서 찾을 수 있습니다. stackoverflow.com/q/6149919
BalusC

답변:


84

환경 내의 모든 리소스는 서버에 의해 관리되고 잠재적으로 모니터링되기 때문에 권장되지 않습니다. 또한 스레드가 사용되는 대부분의 컨텍스트는 일반적으로 실행 스레드 자체에 연결됩니다. 단순히 자신의 스레드를 시작하면 (일부 서버는 허용하지 않을 것이라고 생각합니다) 다른 리소스에 액세스 할 수 없습니다. 이것이 의미하는 바는 InitialContext를 가져올 수없고 JMS 연결 팩토리 및 데이터 소스와 같은 다른 시스템 자원에 액세스하기 위해 JNDI 검색을 수행 할 수 없다는 것입니다.

이 작업을 "올바르게"수행하는 방법이 있지만 사용중인 플랫폼에 따라 다릅니다.

commonj WorkManager는 WebSphere 및 WebLogic 및 기타 공통 사항입니다.

여기에 더 많은 정보

그리고 여기

또한 다소 중복 이 일 이 아침부터를

업데이트 :이 질문과 답변은 2009 년의 Java EE 상태와 관련이 있으며 그 이후로 상황이 개선되었습니다!


1
InitialContext를 가져올 수 없으며 JMS 연결 팩토리 및 데이터 소스와 같은 다른 시스템 자원에 액세스하기 위해 JNDI 검색을 수행 할 수 없습니다. 나는 스레드를 시작할 때 데이터 소스를 주입하여 약이 작동하는 응용 프로그램을 가지고,하지만 난이 방법을 재고해야 할 수도 있습니다 ...
rjohnston

6
이제 핵심 Java EE API를 사용하여 스레드를 생성하는 표준적이고 올바른 방법이 있습니다. Concurrency Utils를 사용하면 컨테이너에서 새 스레드를 만들고 관리하여 모든 EE 서비스를 사용할 수 있습니다. 예를 들면 여기여기에
크리스 리치

@ChrisRitchie 팁 주셔서 감사합니다. JBoss AS / IBM WAS 만 Java EE 7을 지원하는 경우 ... :-(
asgs

1
@asgs 제이보스 8 (JBoss의 AS에 대한 새 이름)를 지원하는 자바 EE 7 IBM은 자바 EE 6 인증을 수행 인증
크리스 리치

34

EJB의 경우 권장 사항 일뿐만 아니라 사양에 의해 명시 적으로 금지되어 있습니다 .

엔터프라이즈 Bean은 여러 인스턴스의 실행을 동기화하기 위해 스레드 동기화 기본 요소를 사용하지 않아야합니다.

엔터프라이즈 Bean은 스레드 관리를 시도하지 않아야합니다. 엔터프라이즈 Bean은 스레드를 시작, 중지, 일시 중단 또는 재개하거나 스레드의 우선 순위 또는 이름을 변경하지 않아야합니다. 엔터프라이즈 Bean은 스레드 그룹을 관리하려고 시도하지 않아야합니다.

그 이유는 EJB가 분산 환경에서 작동하기위한 것입니다. EJB는 클러스터의 한 시스템에서 다른 시스템으로 이동할 수 있습니다. 스레드 (및 소켓 및 기타 제한된 기능)는이 이식성에 대한 중요한 장벽입니다.


3
Java EE7 동시성 유틸리티는 엔터프라이즈 환경에서 스레드를 생성하는 올바른 방법을 제공합니다. 예를 들면 여기여기에
크리스 리치

1
@Dan 스레드가 커 스터의 한 시스템에서 다른 시스템으로 EJB를 이동하는 데 중요한 장벽이되는 이유를 설명해 주시겠습니까?
Geek

13

자신의 스레드를 생성하지 않아야하는 이유는 컨테이너가 스레드를 관리하지 않기 때문입니다. 컨테이너는 초보 개발자가 상상하기 어려운 많은 것들을 처리합니다. 예를 들어 스레드 풀링, 클러스터링, 크래시 복구와 같은 작업은 컨테이너에서 수행됩니다. 스레드를 시작하면 일부가 손실 될 수 있습니다. 또한 컨테이너를 사용하면 실행되는 JVM에 영향을주지 않고 애플리케이션을 다시 시작할 수 있습니다. 컨테이너가 제어 할 수없는 스레드가 있다면 어떻게 가능할까요?

이것이 J2EE 1.4에서 타이머 서비스가 도입 된 이유입니다. 자세한 내용은 기사를 참조하십시오.


2
JSR 236은 Java EE 7 이상에서 스레드 생성을 지원하는 기능을 추가했습니다. Chris Ritchie의 형제 답변을 참조하십시오 .
Basil Bourque


2

배포 설명 자의 일부로 항목을 시작하도록 컨테이너에 항상 지시 할 수 있습니다. 그런 다음 필요한 유지 관리 작업을 수행 할 수 있습니다.

규칙을 따라. 언젠가 당신은 기뻐할 것입니다 :)


2

청사진에 따라 Java EE 컨테이너에서 스레드가 금지됩니다. 자세한 내용은 청사진 을 참조하십시오.


2

그렇게하지 않을 실제 이유가 없습니다. 나는 문제없이 webapp에서 SpringQuarz 를 사용했습니다 . 또한 동시성 프레임 워크를 사용할 수 있습니다. 자체 스레드 처리를 구현하는 경우 컨테이너가 언제든지 웹앱을 언로드 할 수 있도록 theads를 deamon으로 설정 하거나 자체 deamon 스레드 그룹을 사용합니다.java.util.concurrent

그러나 빈 범위 세션요청 은 생성 된 스레드에서 작동하지 않습니다. 또한 다른 코드는 기본적으로 ThreadLocal작동하지 않으므로 생성 된 스레드로 값을 직접 전송해야합니다.


1

나는 그것이 올바르게하기가 쉽지 않다는 사실을 제외하고는 그것이 낙담하다는 것을 읽은 적이 없다.

이것은 상당히 낮은 수준의 프로그래밍이며 다른 낮은 수준의 기술과 마찬가지로 좋은 이유가 있어야합니다. 대부분의 동시성 문제는 스레드 풀과 같은 기본 제공 구조를 사용하여 훨씬 더 효과적으로 해결할 수 있습니다.


7
실제로 사양에 의해 금지되어 있습니다.
Ken Liu

1

EJB에서 일부 스레드를 생성 한 다음 컨테이너를 언로드하거나 EJB를 업데이트하려고하면 문제가 발생할 수있는 한 가지 이유를 찾았습니다. 스레드가 필요하지 않은 작업을 수행하는 다른 방법이 거의 항상 있으므로 아니요라고 말하세요.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.