2013-02-01 2 views
2

작은 응용 프로그램 ("HelloWorld"보다 약간 큰 것)을 쓰고 있습니다. 작업은 단일 제작자와 여러 소비자를 만드는 것입니다. 생산자는 integeres를 생성하여 동적 스택 (이는 내 모니터 객체 임)에 넣고 소비자는 그 정수를 스택에서 가져 오려고합니다. 플래그를 사용하여 1 생산자 + 1 소비자를 생성하는 방법을 알고 있습니다. 그러나 여러 소비자와 동일한 방법. 자바 스레드를 이용한 다중 모니터 동기화

은 내 코드에서 참조하시기 바랍니다 :

public interface StackQueueIF { 
    void push(int value); 
    int pop(); 
} 

public class DynamicStack implements StackQueueIF{ 

    private volatile int stck[]; 
    private volatile int tos; 

    boolean valueSet = false; 

    public DynamicStack(int size) { 
     stck = new int[size]; 
     tos = -1; 
    } 

    @Override 
    public synchronized void push(int item) { 
     while(valueSet){ 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 

     if (tos == stck.length-1) { 
      System.out.println("---------STACK HAS BEEN DOUBLED--------"); 
      int temp[] = new int[stck.length * 2]; 
      for (int i = 0; i < stck.length; i++) temp[i] = stck[i]; 
      stck = temp; 
      stck[++tos] = item; 
     }else 
      stck[++tos] = item; 

     valueSet = true; 
     notifyAll(); 
    } 

    @Override 
    public synchronized int pop() { 
     while(!valueSet){ 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 

     valueSet = false; 
     notifyAll(); 
     return stck[tos--]; 
    } 
} 

class Producer implements Runnable{ 
    StackQueueIF queue; 
    String producerName; 
    private static int counter = 0; 

    public Producer(StackQueueIF queue, String name) { 
     this.queue = queue; 
     this.producerName = name; 
     new Thread(this,producerName).start(); 
    } 

    @Override 
    public void run() { 
     while(true){ 
      System.out.println(this.producerName + " puts " + (++counter) 
       + " into stack"); 
      this.queue.push(counter); 
      try { 
       Thread.sleep(500); 
      } catch (InterruptedException e) { 
       System.err.println(producerName + " interrupted"); 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

class Consumer implements Runnable{ 
    StackQueueIF queue; 
    String consumerName; 

    public Consumer(StackQueueIF queue, String consumerName) { 
     this.queue = queue; 
     this.consumerName = consumerName; 
     new Thread(this, this.consumerName).start(); 
    } 

    @Override 
    public void run() { 
     while(true){ 
      System.out.println(this.consumerName + " gets " + queue.pop() + " from stack"); 
      try { 
       Thread.sleep(500); 
      } catch (InterruptedException e) { 
       System.err.println(consumerName + "interrupted"); 
       e.printStackTrace(); 
      } 
     } 
    } 

} 

public class QueueTester { 
    public static void main(String[] args) { 
     StackQueueIF queue = new DynamicStack(10); 
     new Producer(queue,"Producer №1"); 

     new Consumer(queue,"Consumer №1"); 
     new Consumer(queue,"Consumer №2"); 
    } 
} 
+0

내가 스택을 작성하는 방법이다 스택에서부터 소비자 # 2는 전혀 얻지 못합니다. 그것이 문제이다. 그들은 스택에서 무언가를 얻거나 비어있을 때까지 기다려야합니다. –

+0

+1 사용 №;) –

답변

1

이이 코드를 실행하면, 당신은 단지 소비자 # 1 값을 얻는 것을 볼 수 있습니다

public interface IntStack { 
    void push(int value); 
    int pop() throws InterruptedException; 
} 

public class DynamicStack implements IntStack { 
    private int size = 0, stack[]; 

    public DynamicStack() { 
     this(16); 
    } 

    public DynamicStack(int capacity) { 
     stack = new int[capacity]; 
    } 

    @Override 
    public synchronized void push(int item) { 
     if (size + 1 == stack.length) 
      stack = Arrays.copyOf(stack, stack.length * 2); 
     stack[size++] = item; 
     notifyAll(); // notify() would also do. 
    } 

    @Override 
    public synchronized int pop() throws InterruptedException { 
     while (size == 0) 
      wait(); 
     return stack[--size]; 
    } 
} 
+0

좋은 협조와 도움을 주셔서 감사합니다. 수면 시간을 1ms로 변경하고 10 000 회 반복 한 결과 모든 스레드가 작동 할 수있는 기회가 있음을 알았지 만 일부는 500 회의 반복 작업을 수행하고 나머지는 약간의 변경 작업을 수행하여 5 ~ 10 회의 반복 작업을 수행합니다. 스레드 우선 순위 문제와 Windows 스레드 구현이라고 생각합니다. 도움 주셔서 감사합니다. P. 저는 우크라이나 출신 이었으므로 러시아어로 의견을 입력하고 № 기호를 잊어 버렸습니다 :-) –

+0

스레드가 동시에 실행되며 코드에서 제어하지 않으면 어떻게 동작할지 결정할 수 없습니다. 참고 : 기본적으로 바이어스 잠금을 설정하므로 하나의 스레드가 오랜 시간 동안 선호됩니다. '-XX : -UseBiasedLocking'을 시도하십시오.주의 : 일반적으로 스택이 아닌 큐는 멀티 스레드 시스템에서 사용됩니다. 나는 №의 사용을 좋아하므로 그것을 제거하지 마십시오. ;) –