Java - проблема с потоками - PullRequest
2 голосов
/ 22 июня 2011

У меня есть класс Producer и класс Printer.Производители читают из файла данные для создания PrinttJobs объектов.A 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();
            }

        }
    }
}

1 Ответ

3 голосов
/ 22 июня 2011

Проблема со следующей

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

блокировка может быть не верно после окончания ожидания.Ожидания всегда должны быть в цикле.

Также принтер никогда не уведомляет производителей об изменении блокировки.Вы должны позвонить уведомить, прежде чем вызывать 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();
        }

    }
}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...