2010-01-08 3 views
3

java.nio.channels.Selector와 함께 작업 중이며 각 selectedKey에 대해 읽기/쓰기/수락을위한 준비가되어 있지만 별도의 스레드를 만들고 싶습니다. 같은 소켓이 2 개의 다른 thread에 의해 동시에 처리되지 않는 것을 확인합니다. 그것을하는 가장 좋은 방법은 무엇입니까? 소켓을 처리하고 소켓이 셀렉터에 소켓을 다시 등록하면 스레드를 완성하기 전에 각 selectedKey를 취소 할 생각이었습니다. 스레드의 수명이 다되었지만 효율성이 얼마나 될지 확신하지 못했습니다.java.nio.channels.Selector 동시 처리

답변

9

내 서버를 구축 할 때 나는 다음 자바에서 확장 가능한 I/O에 대한 정말 좋은 더그 레아 presentation,있다. 나는 다음과 같은 접근법을 택했다 : 은 I/O (매우 기본적인 디코딩/인코딩)만을 수행하는 "반응기"내에 하나의 I/O 스레드를 가지고있다. 단순히 바이트와 메시지 개체를 변환 한 다음 들어오는 메시지 개체를 비즈니스 논리 처리를위한 스레드 풀로 전달합니다. I/O 스레드가 포화되지 않는 한 하나 이상의 I/O 스레드이 필요하지 않으며이 스레드에서 다른 프로세스가 발생하기 때문에 대부분의 I/O 병목 현상이 있다고 생각합니다.

당신이 당신의 I/O 쓰레드는 마스터 반응기가 들어오는 연결을 허용함으로써 프리젠 테이션에서 제안 "여러 반응"패턴을 따르는 수 포화 후 procesing을 수행 자식 원자로에 떨어져 손을 증명할 수있는 경우

. 각 자식 반응기는 전체 연결의 하위 집합간에 멀티플렉싱하므로 하나 이상의 스레드가 주어진 SelectionKey과 상호 작용할 위험이 없습니다.

+0

첫 반응은 이것을 권장하기도했습니다. 하지만 이러한 읽기/쓰기/수락 작업 중 일부가 "준비"상태 임에도 불구하고 약간의 지연이 발생하지 않을지는 확실하지 않았습니다. 그러나 Doug Lea도이 방법을 권유한다면 아마도 일을 처리하는 좋은 방법 일 것입니다. –

1

각 소켓마다 별도의 스레드를 만드는 것이 너무 많아 질 수 있다고 생각합니다. 또한 새로운 Thread을 생성하는 것은 실행 시간에 비용이 많이 든다. 스레드 풀을 사용하여 활성 스레드 수를 제한하고 새 스레드 생성을 제한해야합니다. java.util.concurrent.Executors은 고정 된 스레드 풀을 생성하는 기능을 제공합니다. http://java.sun.com/docs/books/tutorial/essential/concurrency/pools.html의 세부 정보.

한 번에 여러 스레드가 닿지 않도록하려는 소켓의 경우 가장 간단한 예외는 다음과 같습니다. 소켓 객체 잠금. 더 효율적인 전략이있을 수 있지만 아마도 더 간단하거나 더 확실한 전략은 없을 것입니다. 이전 반환 소켓의 일부는 처리에 여전히 동안 다른 선택이 완료되면

업데이트

, 당신은 서로 간섭 스레드를 끝낼 수 있었다. 잠금을 통해 다른 스레드를 종료하는 것은 가능하지만 실제로는 우아한 해결책은 아닙니다 (미안). 내가 생각할 수있는

두 대안 :

  • 그것에 당신의 처리 스레드를 시작하기 전에 채널을 등록 해제 및 처리 활동의 마지막에 다시 등록합니다. klutzy는 들리지만 일을 끝내야합니다.

  • 사용자가 진행중인 채널의 데이터 구조를 유지 관리해야합니다. a Set을 찾고 스레드에 제공하기 전에 새로 발견 된 준비 채널을 해당 세트에 추가하고 스레드에서 리턴하기 전에이를 제거하십시오. 선택 세트에서 채널을 처리 할 때 이미 세트에있는 채널은 무시하십시오. 이 집합의 모든 사용은 동기화되어야합니다.

+0

안녕하세요. 회신 해 주셔서 감사합니다. 스레드 풀을 사용 중입니다. 내 문제는 소켓이 여전히 풀에서 스레드에 의해 처리되는 동안 셀렉터에 등록된다는 것입니다. 이렇게하면 스레드 풀에 대한 새 작업이 불필요하게 생성되어 소켓 릴리스 만 필요한 작업이 이미 완료되었음을 알 수 있습니다. 그것은 막으려 고하는 두 번째 작업의 생성입니다. – yuri

+0

너무 늦어서 미안해. 내 대답을 더 많은 제안으로 업데이트했습니다. –