문제

이벤트를 두 번째 스레드의 대기열로 밀어 넣는 스레드의 전형적인 문제가 있습니다. 이번에는 성능에 관심이 있습니다. 내가 달성하고 싶은 것은 다음과 같습니다.

  • 나는 대기열, 생산자 밀고, 수신기가 터지는 동시에 접근하고 싶다.
  • 대기열이 비어 있으면 소비자가 대기열로 차단하여 생산자를 기다리고 싶습니다.

나의 첫 번째 아이디어는 a를 사용하는 것이었다 LinkedBlockingQueue, 그러나 나는 곧 그것이 동시가 아니며 성능이 어려움을 겪었다는 것을 깨달았습니다. 반면에, 나는 이제 a를 사용합니다 ConcurrentLinkedQueue, 그러나 여전히 비용을 지불하고 있습니다 wait() / notify() 각 간행물에서. 소비자가 빈 줄을 찾으면 차단하지 않기 때문에 동기화하고 동기화해야합니다. wait() 자물쇠에. 다른 한편으로, 생산자는 그 자물쇠를 가져와야하고 notify() 모든 출판물에. 전반적인 결과는 내가 비용을 지불하고 있다는 것입니다.sycnhronized (lock) {lock.notify()} 모든 출판물에서 필요하지 않은 경우에도.

내가 여기서 필요하다고 생각하는 것은 차단되고 동시에있는 대기열입니다. 상상합니다 push() 작동하는 작업 ConcurrentLinkedQueue, 추가로 notify() 푸시 된 요소가 목록에서 첫 번째 일 때 객체에. 내가 이미 존재한다고 생각하는 그러한 수표 ConcurrentLinkedQueue, 푸시는 다음 요소와 연결해야합니다. 따라서 이것은 외부 잠금 장치에서 매번 동기화하는 것보다 훨씬 빠릅니다.

이와 같은 것이 사용 가능/합리적입니까?

도움이 되었습니까?

해결책

나는 당신이 고집 할 수 있다고 생각합니다 java.util.concurrent.LinkedBlockingQueue 당신의 의심에 관계없이. 동시에 있습니다. 그러나 나는 그 성능에 대해 전혀 모른다. 아마도 다른 구현 BlockingQueue 당신에게 더 잘 어울릴 것입니다. 그것들이 너무 많지 않으므로 성능 테스트와 측정을 수행하십시오.

다른 팁

이 답과 유사합니다 https://stackoverflow.com/a/1212515/1102730 하지만 조금 다릅니다 .. 나는 결국 ExecutorService. 사용하여 하나를 인스턴스화 할 수 있습니다 Executors.newSingleThreadExecutor(). 파일에 대한 완충 방지 및 읽기 및 쓰기의 원자력을 읽고/쓰기위한 동시 대기열이 필요했습니다. 파일 IO가 소스 인 Net IO보다 훨씬 빠르기 때문에 단일 스레드 만 필요합니다. 또한, 나는 성능보다 행동과 정확성의 원자력에 대해 더 우려했지만,이 접근법은 풀의 여러 스레드를 사용하여 일을 속도를 높일 수 있습니다.

이미지를 얻으려면 (Try-Catch-Finally 생략) :

Future<BufferedImage> futureImage = executorService.submit(new Callable<BufferedImage>() {
    @Override
        public BufferedImage call() throws Exception {
            ImageInputStream is = new FileImageInputStream(file);
            return  ImageIO.read(is);
        }
    })

image = futureImage.get();

이미지를 저장하려면 (Try-Catch-Finally 생략) :

Future<Boolean> futureWrite = executorService.submit(new Callable<Boolean>() {
    @Override
    public Boolean call() {
        FileOutputStream os = new FileOutputStream(file); 
        return ImageIO.write(image, getFileFormat(), os);  
    }
});

boolean wasWritten = futureWrite.get();

최종 블록에서 스트림을 플러시하고 닫아야한다는 점에 유의해야합니다. 나는 그것이 다른 솔루션에 비해 어떻게 작동하는지 잘 모르지만 그것은 매우 다양합니다.

나는 당신이 보는 것이 좋습니다 ThreadPooleExecutor NewsingLethreadExecutor. 그것은 당신의 작업을 당신에게 주문하는 것을 처리하고, 당신이 제출하는 경우 콜블 즈 집행 인에게, 당신은 당신이 찾고있는 차단 동작을 얻을 수 있습니다.

JSR166에서 LinkedTransferqueue를 시도 할 수 있습니다. http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166y/

요구 사항을 충족하고 제안/설문 조사 운영에 대한 오버 헤드가 적습니다. 코드에서 볼 수 있듯이 대기열이 비어 있지 않으면 폴링 요소에 원자 연산을 사용합니다. 그리고 대기열이 비어 있으면 얼마 동안 회전하고 실패한 경우 실을 주차합니다. 나는 그것이 당신의 경우에 도움이 될 수 있다고 생각합니다.

한 스레드에서 다른 스레드로 데이터를 전달해야 할 때마다 ArrayBlockingqueue를 사용합니다. 풋을 사용하고 메소드를 가져옵니다 (전체/비어있는 경우 차단).

여기에 있습니다 구현 클래스 목록 BlockingQueue.

체크 아웃하는 것이 좋습니다 SynchronousQueue.

그의 의견에서 @Rorick과 마찬가지로, 나는 이러한 모든 구현이 동시에 있다고 생각합니다. 나는 당신의 관심사라고 생각합니다 LinkedBlockingQueue 제자리에서 벗어날 수 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top