2011-06-22 62 views
2

我有一个类Producer和一个类Printer。 生产者从文件数据中读取以创建PrinttJobs对象。 A Producer生成一个PrintJob并添加到Queue,通知PrinterProducer比等待1 - 5秒创建新的PrintJobs。 当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(); 
       } 

锁可能不会等待结束后如此。等待应始终处于循环状态。

此外,打印机从不通知生产者锁已经改变。在打印机中打电话等待之前,您应该致电通知。

如果这不是不作业,那么我建议使用阻塞队列来处理所有的等待并通知给你。

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阻塞队列 –

+0

感谢您的回答。如上所述,我改变了'if'for'while',并且在wait()'insinde'halt()'方法之前放了一个'notify()'并且发生了相同的事情。 – Luk

+0

更改您的通话以通知notifyAll。您使用相同的监视器进行多种等待条件,因此您可能会唤醒错误的线程。另外在Producer中等待的最后一个呼叫确实使用了不正确的等待。我会用更好的例子更新我的答案。 –