2016-10-22 1 views
-2

: ArrayBlockingQueue를 (- ") (". 자바가 어떻게 10 프로그램에 대한)ArrayBlockingQueue 객체의 크기가 왜 업데이트되지 않습니까? 나는 장 23.6 Proceducer/소비자 관계에서 예를 들어 다음과 같은거야

나는 예제를 실행하려하지만 난 왜 이해하지 않는다 "buffer.size을 처음에 업데이트되지 않습니다.

내가 소비자 클래스에 약간의 수정을했다. 내가 Thread.sleep(Generator.nextInt(300)) 300 밀리 세컨드 값을 설정합니다. 을 여기에 내 결과입니다.이 코드는

Producer writes 1 Buffer cells occupied: 0 
Consumer reads 1 Buffer cells occupied: 0 
Producer writes 2 Buffer cells occupied: 1 
Consumer reads 2 Buffer cells occupied: 0 
Producer writes 3 Buffer cells occupied: 1 
Consumer reads 3 Buffer cells occupied: 0 
Producer writes 4 Buffer cells occupied: 1 
Consumer reads 4 Buffer cells occupied: 0 
Producer writes 5 Buffer cells occupied: 1 
Consumer reads 5 Buffer cells occupied: 0 
Producer writes 6 Buffer cells occupied: 1 
Consumer reads 6 Buffer cells occupied: 0 
Producer writes 7 Buffer cells occupied: 1 
Consumer reads 7 Buffer cells occupied: 0 
Producer writes 8 Buffer cells occupied: 1 
Consumer reads 8 Buffer cells occupied: 0 
Producer writes 9 Buffer cells occupied: 1 
Consumer reads 9 Buffer cells occupied: 0 
Producer writes10 Buffer cells occupied: 1 
Producer done producing 
Terminating producer 
Consumer reads 10 Buffer cells occupied: 0 

Consumer reads values totaling 55 
Terminating Consumer 

입니다.

public class BlockingBufferTest { 
public static void main(String[] args) throws InterruptedException { 
    ExecutorService executorService = Executors.newCachedThreadPool(); 

    BlockingBuffer sharedLocation = new BlockingBuffer(); 

    executorService.execute(new Producer(sharedLocation)); 
    executorService.execute(new Consumer(sharedLocation)); 

    executorService.shutdown(); 
    executorService.awaitTermination(1, TimeUnit.MINUTES); 

} // end main method 
} // end class 

public class BlockingBuffer implements Buffer { 

private final ArrayBlockingQueue<Integer> buffer; // shared buffer 

public BlockingBuffer() { 
    buffer = new ArrayBlockingQueue<>(1); 
} 
@Override 
public void blockingPut(int value) throws InterruptedException { 
    buffer.put(value); // place value in buffer 
    System.out.printf("%s%2d\t%s%d%n", "Producer writes", value, "Buffer cells occupied: ", buffer.size()); 
} 

@Override 
public int blockingGet() throws InterruptedException { 
    int readValue = buffer.take(); // remove value from buffer 
    System.out.printf("%s %2d\t%s%d%n", "Consumer reads", readValue, "Buffer cells occupied: ", buffer.size()); 
    return readValue; 
} 
} 

public class Consumer implements Runnable { 

private static final SecureRandom generator = new SecureRandom(); 
private final Buffer sharedLocation; // reference to shared object 

public Consumer(Buffer sharedLocation) { 
    this.sharedLocation = sharedLocation; 
} // end constructor 

// stores values 1 to 10 in sharedLocation 
@Override 
public void run() { 
    int sum = 0; 
    for(int count=1; count<=10; count++) { 
     try { 
      Thread.sleep(generator.nextInt(300));// random sleep 
      sum +=sharedLocation.blockingGet(); 

     } catch (InterruptedException e) { 
      Thread.currentThread().interrupt(); 
     } 
    } // end for 

    System.out.printf("%n%s %d%n%s%n","Consumer reads values totaling", sum, "Terminating Consumer"); 
} // end run method 
} 

public class Producer implements Runnable { 

private static final SecureRandom generator = new SecureRandom(); 
private final Buffer sharedLocation; // reference to shared object 

public Producer(Buffer sharedLocation) { 
    this.sharedLocation = sharedLocation; 
} // end constructor 

// stores values 1 to 10 in sharedLocation 
@Override 
public void run() { 
    int sum = 0; 
    for(int count=1; count<=10; count++) { 
     try { 
      Thread.sleep(generator.nextInt(3000));// random sleep 
      sharedLocation.blockingPut(count); 
      sum += count; 

     } catch (InterruptedException e) { 
      Thread.currentThread().interrupt(); 
     } 
    } // end for 

    System.out.printf("Producer done producing%nTerminating producer%n"); 
} // end run method 
} 

답변

0

이것은 스레드 주문/선점 멀티 태스킹의 아티팩트처럼 보입니다.

기본적으로 생산자/소비자의주기는 각각 원자 적이지 않습니다. 그들은 한주기의 사이에 서로를 선점 할 수 있습니다.

Producer thread: put value    (size=1) 
Consumer thread: read value    (size=0) 
Producer thread: x1 = buffer.size() --> x1 = 0 
Producer thread: print x1 --> you observe 'Producer writes 1 Buffer cells occupied: 0' 
Consumer thread: x2 = buffer.size() --> x2 = 0 
Consumer thread: print x --> you observe 'Consumer reads 1 Buffer cells occupied: 0' 

P.S.을 : 여기

예를 들어 작업의 순서가 작동하는 방법이다 실제로 조금 더 까다 롭고 모든 작업의 ​​선형 순서는 없지만 일부 그룹 만 있지만이 설명에서는 괜찮습니다.

+0

Thanks Ivan. :) – Hikaru