gpt4 book ai didi

Java - 线程问题

转载 作者:行者123 更新时间:2023-12-03 12:57:10 27 4
gpt4 key购买 nike

我有一个类Producer和一个类(class)Printer .
生产者从文件中读取数据以创建 PrinttJobs对象。
一个 Producer生成一个 PrintJob并添加到 Queue ,通知 Printer . Producer比等待 1 - 5 秒创建新 PrintJobs .
Printer通知它打开并从队列中获取作业并打印它们。本期Producer不能工作。 Printer打印所有内容并再次等待,让 Producer再次工作。
该应用程序适用于 2 个生产者和 1 个打印机。
我的问题是有时它运行良好,有时它不会打印出所有东西。我也认为我的 wait时间限制 1-5 秒效果不佳/可能是问题所在。代码如下:

已编辑

当生产者实际生产某些东西时,他们几乎总是同时发送。有时它会停止生成但文件中的数据仍然存在。

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();
}

}
}
}

最佳答案

问题在于以下

                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();
}

}
}
}

关于Java - 线程问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6441271/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com