2011-06-22 9 views
2

私はクラスProducerとクラスPrinterを持っています。 プロデューサはファイルからデータを読み取り、PrinttJobsオブジェクトを作成します。 Producerは、PrintJobを生成し、Queueに追加し、Printerを通知します。新しいPrintJobsを作成するのに1〜5秒待機するよりもProducerです。 Printerが通知されていない場合は、オンになりジョブをキューから取得して印刷します。この期間にProducerは動作しません。 Printerはすべてを印刷し、もう一度待ってProducerを再び動作させます。 アプリは2つのプロデューサと1つのプリンタで動作します。 私の問題は時にはそれがうまくいくことです、時にはそれはすべてのものを印刷しないことです。また、私のwaitの時間制限は1〜5秒でうまくいきません/問題かもしれないと思います。コードは以下の通りです:Java - スレッドに関する問題

EDITED

生産者が実際に何かを作るとき、彼らはほとんど常に同時に送信します。そして時には、ファイル内のデータを生成することも止めます。

class Printer implements Runnable { 

    protected long MILLIS_PER_PAGE = 500; 

    private String name; 
    Queue queue; 
    boolean lock = false; 

    public Printer(String name, Queue queue) { 
     this.name = name; 
     this.queue = queue; 
    } 

    public String getPrinterName() { 
     return name; 
    } 

    @Override 
    public void run() { 
     System.out.println("["+getPrinterName()+"] Ligando..."); 
     while(true) { 
      synchronized(this){ 
       if(queue.isEmpty()) { 
        try { 
         System.out.println("["+getPrinterName()+"] Esperando por tabalho de impressão..."); 
         lock = false; 
         halt(); 
        } 
        catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 

       } 
       else { 
        lock = true; 
        PrintJob pj = queue.removeFront(); 
        System.out.println("Imprimindo "+ pj.getJobName()); 
        try { 
         wait(pj.getNumberOfPages() * MILLIS_PER_PAGE); 
         System.out.println(pj.getJobName() + " ok."); 
        } 
        catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 


       } 
      } 
     } 
    } 

    public void halt() throws InterruptedException { 

     wait(); 

    } 

} 
` 

` 
import java.io.FileNotFoundException; 
import java.io.FileReader; 
import java.io.IOException; 
import java.util.Scanner; 

class Producer implements Runnable { 

    private String name; 
    Queue queue; 

    String job; 
    int pags; 
    String arquivo; 

    public Producer(String name, Queue queue, String arquivo) { 
     this.name = name; 
     this.queue = queue; 
     this.arquivo = arquivo; 
    } 

    public String getProducerName() { 
     return name; 
    } 

    @Override 
    public void run(){ 
     synchronized (PrinterApp.printer) { 

      FileReader fin; 

      try { 
       fin = new FileReader(arquivo); 
       Scanner src = new Scanner(fin); 

       while (src.hasNext()) { 
        if (PrinterApp.printer.lock == true){ 
         PrinterApp.printer.wait(); 
        } 
        job = src.next(); 
        pags = src.nextInt(); 
        PrintJob p = new PrintJob(job, pags); 

        queue.addBack(p); 

        System.out.println("["+getProducerName()+"] produzindo arquivo " + job +", número de páginas: " + pags); 
        PrinterApp.printer.notify(); 
        PrinterApp.printer.wait(1000 + (int)Math.round((Math.random() * (5000 - 1000)))); 

       } 
       fin.close(); 
      } 


      catch (FileNotFoundException e) { 
       e.printStackTrace(); 

      } 
      catch (QueueException e) { 

       e.printStackTrace(); 
      } 

      catch (IOException e) { 
       e.printStackTrace(); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

     } 
    } 
} 
+0

は、オペレーティング・システムのクラスからの割り当てのような非常に多く、私はキュー答えを – Woot4Moo

答えて

3

問題があると、次の

   if (PrinterApp.printer.lock == true){ 
        PrinterApp.printer.wait(); 
       } 

ロックが待機終了後に真ではないかもしれません。待ちは常にループになっていなければなりません。

また、プリンタはロックが変更されたことをプロデューサに通知しません。プリンタでwaitを呼び出す前にnotifyを呼び出す必要があります。

これは宿題ではない場合は、すべての待機を処理して通知するブロックキューを使用することをおすすめします。

class Printer implements Runnable { 

protected long MILLIS_PER_PAGE = 500; 

private String name; 
Queue queue; 
boolean lock = false; 

public Printer(String name, Queue queue) { 
    this.name = name; 
    this.queue = queue; 
} 

public String getPrinterName() { 
    return name; 
} 

@Override 
public void run() { 
    System.out.println("["+getPrinterName()+"] Ligando..."); 
    while(true) { 
     synchronized(this){ 
      if(queue.isEmpty()) { 
       try { 
        System.out.println("["+getPrinterName()+"] Esperando por tabalho de impressão..."); 
        lock = false; 
        notifyAll(); 
        halt(); 
       } 
       catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 

      } 
      else { 
       lock = true; 
       PrintJob pj = queue.removeFront(); 
       System.out.println("Imprimindo "+ pj.getJobName()); 
       try { 
        wait(pj.getNumberOfPages() * MILLIS_PER_PAGE); 
        System.out.println(pj.getJobName() + " ok."); 
       } 
       catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 


      } 
     } 
    } 
} 

public void halt() throws InterruptedException { 

    wait(); 

} 

} 
import java.io.FileNotFoundException; 
import java.io.FileReader; 
import java.io.IOException; 
import java.util.Scanner; 

class Producer implements Runnable { 

private String name; 
Queue queue; 

String job; 
int pags; 
String arquivo; 

public Producer(String name, Queue queue, String arquivo) { 
    this.name = name; 
    this.queue = queue; 
    this.arquivo = arquivo; 
} 

public String getProducerName() { 
    return name; 
} 

@Override 
public void run(){ 
    FileReader fin; 

    try { 
     fin = new FileReader(arquivo); 
     Scanner src = new Scanner(fin); 

     while (src.hasNext()) {      
     synchronized (PrinterApp.printer) { 
       while (PrinterApp.printer.lock == true){ 
        PrinterApp.printer.wait(); 
       } 
       job = src.next(); 
       pags = src.nextInt(); 
       PrintJob p = new PrintJob(job, pags); 

       queue.addBack(p); 

       System.out.println("["+getProducerName()+"] produzindo arquivo " + job +", número de páginas: " + pags); 
       PrinterApp.printer.notifyAll(); 
      } 
      // don't wait here since your not waiting on a condition to change 
      Thread.sleep(1000 + (int)Math.round((Math.random() * (5000 - 1000)))); 

      } 
      fin.close(); 
     } 


     catch (FileNotFoundException e) { 
      e.printStackTrace(); 

     } 
     catch (QueueException e) { 

      e.printStackTrace(); 
     } 

     catch (IOException e) { 
      e.printStackTrace(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

    } 
} 
} 
+0

1年前を取ったに見えます。あなたが言ったように 'while'の' if 'を変更し、 'wait()' insinde 'halt()'メソッドの前に 'notify()'を入れて同じことが起こりました。 –

+0

感謝を阻止するための – Luk

+0

通知する通知をnotifyAllに変更します。複数の待機条件に対して同じモニターを使用しているため、間違ったスレッドを起動する可能性があります。また、プロデューサで最後に待機する呼び出しは、実際には間違ってwaitを使用しています。私は良い例で私の答えを更新します。 –

関連する問題