我有一个班级Producer
和一个班级Printer
。
生产者从文件数据中读取以创建PrinttJobs
个对象。
Producer
生成一个PrintJob
并添加到Queue
,通知Printer
。 Producer
比等待1到5秒创建新的PrintJobs
。
当Printer
未通过时,它会打开并从队列中获取作业并打印它们。在此期间Producer
无效。 Printer
打印所有内容并再次等待,让Producer
再次运行。
该应用程序适用于2个生产者和1个打印机。
我的问题是,有时它会顺利进行,有时它不会打印产生一切。另外我认为我的wait
时间限制为1-5秒不能正常工作/可能是问题所在。代码如下:
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 :(得分: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();
}
}
}
}