2009-07-10 8 views
6

내 응용 프로그램의 다른 쪽에서 외부 시스템과 연결되어 등록 된 클라이언트를 나타 내기 위해 클래스의 객체를 인스턴스화하는 Java 응용 프로그램을 작성하고 있습니다.자바 - 논 블로킹 소켓 용 다중 스레드의 다중 선택자

각 클라이언트 개체에는 프런트 엔드와 백 엔드를 나타내는 두 개의 중첩 된 클래스가 있습니다. 프론트 엔드 클래스는 실제 클라이언트로부터 계속해서 데이터를 수신하고 프런트 엔드에서 해당 데이터를 가져 와서 적절한 형식 및 프로토콜을 사용하여 외부 시스템으로 전송하는 백엔드 클래스에 표시 및 데이터를 보냅니다. 해당 시스템에 필요합니다.

디자인에서는 클라이언트 객체의 각 인스턴스화를 스레드로 만들려고합니다. 그런 다음, 각 스레드 내에서 당연히 프론트 엔드와 백엔드에 각각 하나의 클라이언트 측, 하나의 시스템 측에 각각 고유 한 NIO 채널 [편집]이있는 두 개의 소켓 [EDIT]이됩니다. 그러나 이제 비 블로킹 소켓이 필요합니다. 필자는 here 튜토리얼을 읽고 있는데, 주 ​​스레드에서 Selector를 사용하여 안전하게 모든 연결 스레드를 처리하는 방법을 설명합니다.

하지만 필자가 필요로하는 것은 다중 선택기 (각 선택기는 자체 스레드에서 작동)입니다. 앞에서 설명한 튜토리얼을 읽으면서 Selector의 키 세트가 threadsafe가 아니라는 것을 알게되었습니다. 이것은 각각 소켓과 채널 쌍을 제공하려고 시도 할 때 각각의 repsective 스레드에서 인스턴스화 된 개별 Selector가 충돌하는 키를 생성 할 수 있다는 것을 의미합니까? 셀렉터를 주 스레드로 옮기는 것은 약간의 가능성이 있지만, 필자가 제공 한 소프트웨어 요구 사항에 따라 이상적인 것은 아닙니다. 도와 줘서 고마워.

답변

3

선택기 인스턴스를 사용하여 동일한 관심사 (OP_READ/OP_WRITE 등)로 같은 채널을 등록하지 않는 한 다중 선택기를 사용하면 좋습니다. 동일한 셀을 여러 선택기 인스턴스에 등록하면 selector1.select()에서 selector2.select()가 관심을 가질 수있는 이벤트를 사용할 수있는 문제가 발생할 수 있습니다.

대부분의 플랫폼에서 기본 선택기는 poll() [ 또는 epoll()]을 기반으로합니다.

Selector.select 내부적으로 ROX의 RPC NIO 튜토리얼에서 언급 한 바와 같이, 나는 하나의 선택 스레드의 사용을 추천 할 것입니다 말했다 int poll(ListPointer, Nfdsmsgs, Timeout) method.

 where the ListPointer structure can then be initialized as follows: 

    list.fds[0].fd = file_descriptorA; 
    list.fds[0].events = requested_events; 
    list.msgs[0].msgid = message_id; 
    list.msgs[0].events = requested_events; 

호출합니다. NIO 구현은 플랫폼에 따라 다르며 한 플랫폼에서 작동하는 것이 다른 플랫폼에서 작동하지 않을 수도 있습니다. 마이너 버전에서도 문제가 발생했습니다. 예를 들어, AIX JDK 1.6 SR2는 poll() 기반 선택기 - PollSelectorImpl과 해당 선택기 공급자를 PollSelectorProvider로 사용하여 서버가 정상적으로 실행되었습니다. pollset 인터페이스 기반의 최적화 된 선택기 (PollSetSelectorImpl)를 사용하는 AIX JDK 1.6 SR5로 이동했을 때 우리 서버에서 select() 및 socketchannel.close()가 자주 중단되었습니다. 내가 본 한 가지 이유는 응용 프로그램에서 (선택적인 스레드 선택 모델과 반대되는) 여러 개의 선택기를 열고 here과 같이 PollSetSelectorImpl을 구현 한 것입니다.

3

이 단일 소켓 연결을 사용해야하는 경우 데이터 처리 자체에서 채널 수신 및 수신 프로세스를 채널과 분리해야합니다. 채널을 위임하지 않아도됩니다. 채널은 버스와 같습니다. 버스 (채널을 관리하는 단일 스레드)는 데이터를 읽고 필요한 정보를 포함하여 (쓰레드 - 안전) 입력 대기열에 쓰도록해야합니다. 그래서 클라이언트 스레드는 올바른 데이터 그램 패키지를 선택할 수 있습니다. 대기열. 클라이언트 스레드가 데이터 쓰기를 좋아하면 해당 데이터는 출력 대기열에 쓰여지고 출력 대기열은 채널 스레드에 의해 읽혀 채널에 데이터를 씁니다.

이 연결을 사용하는 액터 간의 연결을 예측할 수없는 처리 시간 (블록의 주된 이유 임)으로 공유한다는 개념에서 비동기 데이터 읽기, 데이터 처리 및 데이터 쓰기라는 개념으로 이동합니다. 따라서 더 이상 예측할 수없는 처리 시간은 아니지만 시간은 데이터를 읽거나 쓰는 시간입니다. 비 차단은 데이터를 처리하는 데 필요한 시간에도 불구하고 데이터 스트림이 가능한 한 일정하다는 것을 의미합니다.

+0

나는 당신의 대답에 약간 혼란 스럽다. 채널 자체가 스레드인지, 채널이 자체 스레드인지 또는 별도의 채널을 설정하고 폴링해야한다고 말하고 있습니까? thread from the clients? 각 클라이언트 객체에는 두 개의 소켓과 응용 프로그램의 양쪽에서 통신하는 두 개의 채널이있을 것입니다. 원래 C에서 소켓을 작성하는 방법을 배우면서 비 블로킹 대 비 블로킹이라는 개념에 익숙하며 멀티플렉싱 된 통신에 대한 요구 때문에 비 블로킹을 특별히 선택했습니다. –

+1

이것은 조심성이 있습니다. 제발, 다운 득표 없음 ... 시스템 쟁점 토론을 참조하십시오. : http://www.ibm.com/developerworks/aix/library/au-pollset/index.html 더 나은 대답을 제공합니다. 스레딩 thingamabob : 좋은 io와 스레딩 성능을 원하는 프로그래밍 컨텍스트에서 작동하도록 설계되었습니다. 전체 문제는 Real-Time JSR에 설명 된 문제로 심하게 흐려집니다. 위 링크를 통해 문제에 대한 정보를 얻은 엔지니어가 문제에 대한 토론을 할 수 있습니다. 나는 초기 테스트를 해봤 다. –