2014-11-19 2 views
0

Я пытаюсь решить проблему производителя с потоками в java, но код не будет работать параллельно или параллельно. Производитель всегда заполняет буфер полностью, прежде чем потребитель начнет потреблять, и я не понимаю почему. Точка пытается это сделать, используя только синхронизированные блоки, wait() и notify().Попытка решить потребитель-производитель в java с многопоточным

Главная:

String [] data = {"Fisk", "Katt", "Hund", "Sau", "Fugl", "Elg", "Tiger", 
       "Kameleon", "Isbjørn", "Puma"}; 
    ProducerConsumer pc = new ProducerConsumer(5); 
    Thread[] thrds = new Thread[2]; 
    thrds[0] = new Thread(new MyThread1(pc, data)); // producer 
    thrds[1] = new Thread(new MyThread2(pc)); // consumer 
    thrds[0].start(); 
    thrds[1].start(); 
    for(int i = 0; i < 2; i++) { // wait for all threads to die 
     try { 
      thrds[i].join(); 
     } 
     catch (InterruptedException ie) {} 
    } 
    System.exit(0); 

ProducerConsumer.java:

import java.util.LinkedList; 
import java.util.Queue; 

public class ProducerConsumer implements Runnable { 
    private int bufferSize; 
    private Queue<String> buffer; 

public ProducerConsumer(int size) { 

    bufferSize = size; 
    buffer = new LinkedList<String>(); 
} 

public void produce(String item) throws InterruptedException { 
     synchronized(buffer) { 
      while (buffer.size() >= bufferSize) { 
       try { 
        System.out.println("Full buffer. Waiting for consumer..."); 
        buffer.wait(); 
       }catch (Exception e) {} 
      } 
      buffer.add(item); 
      System.out.println("Producer is putting " + item + " in the buffer"); 
      buffer.notify(); 
     } 
} 

public void consume() throws InterruptedException { 
    synchronized (buffer) { 
     while (buffer.size() == 0) { 
      try { 
       System.out.println("Empty buffer. Waiting for production..."); 
       buffer.wait(); 
      }catch (Exception e) {} 
     } 
     System.out.println("Consumer is consuming " + buffer.remove() + "."); 
     buffer.notify(); 
    } 
} 

@Override 
public void run() { 
} 

}

MyThread1:

/* 
* PRODUCER - Thread 
*/ 
public class MyThread1 implements Runnable { 

private String [] data; 
private ProducerConsumer pc; 

public MyThread1(ProducerConsumer pc, String [] data) { 
    this.pc = pc; 
    this.data = data; 
} 
@Override 
public void run() { 
    for (int i = 0; i < data.length; i++) { 
     try { 
      pc.produce(data[i]); 
     } catch (InterruptedException ex) {} 
    } 
} 

} 

MyThread2:

// ПОТРЕБИТЕЛЯ - Thread

public class MyThread2 implements Runnable{ 

private ProducerConsumer pc; 

public MyThread2(ProducerConsumer pc) { 
    this.pc = pc; 
} 

//Run consume 
@Override 
public void run() { 
    while (true) { 
     try { 
      pc.consume(); 
      Thread.sleep(2); 
     } 
     catch(InterruptedException e) {} 

    } 

} 
} 
+0

Я думаю из-за 'synchronized (buffer)' –

+1

A) Это какое-то назначение или у вас есть другие причины не использовать [BlockingQueue] (https://docs.oracle.com/javase/7/ документы/API/Java/Util/параллельный/BlockingQueue.html)? B) нет кода для предотвращения того, что производитель работает так быстро, как есть. Если вы хотите, чтобы это произошло, возможно, дайте ему спать или так? Нити не имеют заданного времени синхронизации, и первый запуск потока может завершиться до того, как вы начнете второй. – zapl

+1

И почему ProducerConsumer реализует Runnable? –

ответ

0

На последних машины, с короткими очередями, как это, вы никогда не будете видеть реальные многопоточные эффекты, такие как, в этом случае производитель и потребитель по очереди, если вы не замедлите их оба немного вниз. Вы только затормозили потребителя. Вместо того, чтобы использовать короткий массив, поставьте миллион целых чисел в очередь и посмотрите, что произойдет.

Смежные вопросы