2012-05-01 2 views
0

Я занимаюсь проектом моделирования симулятора CPU для своего курса ОС. Программа должна состоять из двух потоков: потоки производителей и потребителей. Нить производителя включает генератор, который генерирует процессы в системе и долгосрочный планировщик, который выбирает несколько процессов и помещает их в объект Buffer типа ReadyQueue (который является общим объектом потребителем и производителем). Потребительский поток включает в себя краткосрочный планировщик, который принимает процессы из очереди и запускает алгоритм планирования. Я написал всю программу без использования потоков, и она работала правильно, но теперь мне нужно добавить потоки, и я никогда не использовал потоки, поэтому я ценю, может ли кто-нибудь показать мне, как изменить код, который я показываю ниже, для реализации необходимых потоков.Продюсер/Потребительские потоки не дают результатов

Вот реализация класса Производитель:

public class Producer extends Thread{ 

    ReadyQueue Buffer = new ReadyQueue(20); // Shared Buffer of size 20 between consumer and producer 
    JobScheduler js = new JobScheduler(Buffer); 

    private boolean systemTerminate = false; // Flag to tell Thread that there are no more processes in the system 

    public Producer(ReadyQueue buffer) throws FileNotFoundException{ 
     Buffer = buffer; 
     Generator gen = new Generator(); // Generator generates processes and put them in a vector called memory  
     gen.writeOnFile(); 
    } 

    @Override 
    public void run() { 

     synchronized(this){ 
      js.select(); // Job Scheduler will select processes to be put in the Buffer 

      Buffer = (ReadyQueue) js.getSelectedProcesses(); 

      while(!Buffer.isEmpty()){  
       try { 
        wait();  // When Buffer is empty wait until getting notification 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       systemTerminate = js.select(); 
       Buffer = (ReadyQueue) js.getSelectedProcesses(); 
       if(systemTerminate)  // If the flag's value is true the thread yields 
        yield(); 
      } 
     } 
    } 

    public ReadyQueue getReadyQueue(){ 
     return Buffer; 
    } 
} 

Это реализация потребительского класса:

public class Consumer extends Thread{ 

    ReadyQueue Buffer = new ReadyQueue(20); 
    Vector<Process> FinishQueue = new Vector<Process>(); 
    MLQF Scheduler ; 
    public Consumer(ReadyQueue buffer){ 
     Buffer = buffer; 
     Scheduler = new MLQF(Buffer,FinishQueue); // An instance of the multi-level Queue Scheduler 
    } 

    @Override 
    public void run() { 
     int count = 0;   // A counter to track the number of processes 

     while(true){ 
      synchronized(this){ 
       Scheduler.fillQueue(Buffer); // Take contents in Buffer and put them in a separate queue in the scheduler 
         Scheduler.start();    // Start Scheduling algorithm 
       count++; 
      } 
      if(count >= 200) // If counter exceeds the maximum number of processes thread must yeild 
       yield(); 
      notify();    // Notify Producer thread when buffer is empty 
     } 
    } 

    public void setReadyQueue(ReadyQueue q){ 
     Buffer = q; 
    } 
} 

Это главная тема:

public class test { 

    public static void main(String[] args) throws FileNotFoundException,InterruptedException {  
     ReadyQueue BoundedBuffer = new ReadyQueue(20); 
     Producer p = new Producer(BoundedBuffer); 
     Consumer c = new Consumer(p.getReadyQueue()); 
     p.start(); 
     System.out.println("Ready Queue: "+p.getReadyQueue()); 
     p.join(); 
     c.start(); 
     c.join(); 
     } 
} 

Спасибо заранее.

ответ

1

Одна из проблем с кодом заключается в том, что он страдает от общей ошибки в многопоточных моделях производителя/потребителя. Вы должны использовать while посмотреть вокруг звонков wait(). Например:

try { 
    // we must do this test in a while loop because of consumer race conditions 
    while(!Buffer.isEmpty()) { 
     wait();  // When Buffer is empty wait until getting notification 
     ... 
    } 
} catch (InterruptedException e) { 
    e.printStackTrace(); 
} 

Вопрос заключается в том, что если у вас есть несколько потоков, которые потребляют, вы можете notify нить а потом другой поток заставил прийти через и из очереди элемента, который был только что добавил. Когда поток перемещается из очереди WAIT в очередь RUN после уведомления, он обычно помещается в конец очереди, возможно, за другими потоками, ожидающими синхронизации на this.

Подробнее об этом см. На моем documentation about this.

+0

Благодарим вас за ответ Серый. Не могли бы вы уточнить, какой поток вызывает эту ошибку? Потребитель или производитель? Или, может быть, покажите мне, как это исправить, поскольку я новичок в потоках. – Samantha

+0

Также метод 'notify' должен находиться в блоке' synchronized'. – Gray

+0

Ошибка находится в потребительском 'while (true)' loop @Samantha. Ссылка, которую я предоставил в своем ответе, содержит все детали. Всякий раз, когда вы являетесь 'wait()' в таком состоянии, как вы это делаете у потребителя, вы должны снова проверить условие, в котором вы ожидали. – Gray

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